ES6-Iterator

16624 단어 ES6JavaScript
Iterator
소개 하 다.
기 존의 집합 을 나타 내 는 데이터 구 조 는 주로 배열 과 대상 이 고 ES6 는 Map 과 Set 을 추 가 했 으 며 Iterator 는 통 일 된 인터페이스 체제 로 서로 다른 데이터 구 조 를 처리 하 는 데 사용 되 었 다.
  • Iterator 는 일종 의 인터페이스 로 각종 서로 다른 데이터 구조 에 통 일 된 방문 메커니즘 을 제공한다
  • 모든 데이터 구 조 는 Iterator 인 터 페 이 스 를 배치 하면 이런 데이터 구 조 를 옮 겨 다 닐 수 있다 고 한다
  • .
  • ES6 는 기본 Iterator 인터페이스 가 데이터 구조의 Symbol. iterator 속성 에 배치 되도록 규정 하고 있다
  •  //    Symbol.iterator  
     let arr = ['a', 'b', 'c'];
     let iter = arr[Symbol.iterator]();
    
     iter.next() // { value: 'a', done: false }
     iter.next() // { value: 'b', done: false }
     iter.next() // { value: 'c', done: false }
     iter.next() // { value: undefined, done: true }
    

    역할.
  • 각종 데이터 구조 에 통일 되 고 간편 한 액세스 인터페이스 제공
  • 데이터 구조의 구성원 을 특정한 순서에 따라 배열 할 수 있 게 한다
  • ES6 는 새로운 스 트 리밍 명령 for... of 순환 을 만 들 었 고 Iterator 인 터 페 이 스 는 주로 for... of 소비
  • 를 제공 합 니 다.
    과정 을 편력 하 다
  • 포인터 대상 을 만 들 고 현재 데이터 구조의 시작 위 치 를 가리킨다.즉, 스 트 리밍 대상 은 본질 적 으로 지침 대상
  • 이다.
  • 포인터 대상 을 처음 호출 하 는 next 방법 으로 데이터 구조의 첫 번 째 구성원
  • 을 가리 킬 수 있 습 니 다.
  • 두 번 째 포인터 대상 을 호출 하 는 next 방법 은 데이터 구조의 두 번 째 구성원
  • 을 가리킨다.
  • 포인터 대상 next 방법 을 계속 호출 하여 데이터 구조의 끝 위 치 를 가리 킬 때 까지
  • //   next     
    var it = makeIterator(['a', 'b']);
    
    it.next() // { value: "a", done: false }
    it.next() // { value: "b", done: false }
    it.next() // { value: undefined, done: true }
    
    function makeIterator(array) {
      var nextIndex = 0;
      return {
        next: function() {
          return nextIndex < array.length ?
            {value: array[nextIndex++], done: false} :
            {value: undefined, done: true};
        }
      };
    }

    원생 Iterator 인터페이스 데이터 구 조 를 갖 춘:
  • Array
  • Map
  • Set
  • TypedArray
  • 함수 의 arguments 대상
  • NodeList 대상
  • 대상 (Object) 이 Iterator 인 터 페 이 스 를 기본 으로 배치 하지 않 은 이 유 는 대상 의 어떤 속성 이 먼저 옮 겨 다 니 고 어떤 속성 이 옮 겨 다 니 는 지 확실 하지 않 기 때문에 개발 자가 수 동 으로 지정 해 야 합 니 다.본질 적 으로 스 트 리밍 기 는 일종 의 선형 처리 로 그 어떠한 비 선형 데이터 구조 에 대해 스 트 리밍 기 인 터 페 이 스 를 배치 하 는 것 은 일종 의 선형 전환 을 배치 하 는 것 과 같다.
    대상 이 for... of 순환 호출 가능 한 Iterator 인 터 페 이 스 를 갖 추 려 면 Symbol. iterator 속성 에 스 트 리밍 기 생 성 방법 을 배치 해 야 합 니 다.
    //        Iterator      。Symbol.iterator        ,               
    class RangeIterator {
      constructor(start, stop) {
        this.value = start;
        this.stop = stop;
      }
    
      [Symbol.iterator]() { return this; }
    
      next() {
        var value = this.value;
        if (value < this.stop) {
          this.value++;
          return {done: false, value: value};
        }
        return {done: true, value: undefined};
      }
    }
    
    function range(start, stop) {
      return new RangeIterator(start, stop);
    }
    
    for (var value of range(0, 3)) {
      console.log(value); // 0, 1, 2
    }
    //            
    //               Symbol.iterator  ,             iterator,      next  ,         ,              
    function Obj(value) {
      this.value = value;
      this.next = null;
    }
    
    Obj.prototype[Symbol.iterator] = function() {
      var iterator = { next: next };
    
      var current = this;
    
      function next() {
        if (current) {
          var value = current.value;
          current = current.next;
          return { done: false, value: value };
        } else {
          return { done: true };
        }
      }
      return iterator;
    }
    
    var one = new Obj(1);
    var two = new Obj(2);
    var three = new Obj(3);
    
    one.next = two;
    two.next = three;
    
    for (var i of one){
      console.log(i); // 1, 2, 3
    }
    //      Iterator    
    let obj = {
      data: [ 'hello', 'world' ],
      [Symbol.iterator]() {
        const self = this;
        let index = 0;
        return {
          next() {
            if (index < self.data.length) {
              return {
                value: self.data[index++],
                done: false
              };
            } else {
              return { value: undefined, done: true };
            }
          }
        };
      }
    };

    유사 한 배열 의 대상 (수치 키 이름과 length 속성 이 존재 함) 에 대해 Iterator 인 터 페 이 스 를 배치 하 는 간단 한 방법 은 Symbol. iterator 방법 으로 배열 의 Iterator 인 터 페 이 스 를 직접 참조 하 는 것 입 니 다.
    // NodeList           ,         ,      
    NodeList.prototype[Symbol.iterator] = Array.prototype[Symbol.iterator];
    //   
    NodeList.prototype[Symbol.iterator] = [][Symbol.iterator];
    
    [...document.querySelectorAll('div')] //      
    
    //                   Symbol.iterator     
    let iterable = {
      0: 'a',
      1: 'b',
      2: 'c',
      length: 3,
      [Symbol.iterator]: Array.prototype[Symbol.iterator]
    };
    for (let item of iterable) {
      console.log(item); // 'a', 'b', 'c'
    }

    주: 일반 대상 에 배열 을 배치 하 는 Symbol. iterator 방법 은 효과 가 없습니다.
    let iterable = {
      a: 'a',
      b: 'b',
      c: 'c',
      length: 3,
      [Symbol.iterator]: Array.prototype[Symbol.iterator]
    };
    for (let item of iterable) {
      console.log(item); // undefined, undefined, undefined
    }
    

    Symbol. iterator 방법 에 대응 하 는 스 트 리밍 생 성 함수 가 아니라면 엔진 설명 이 잘못 되 었 습 니 다.
    var obj = {};
    obj[Symbol.iterator] = () => 1;
    [...obj] // TypeError: [] is not a function

    Iterator 인터페이스 호출 장소
  • 구조 할당: 배열 과 Set 구 조 를 할당 할 때 기본 호출
  • Symbol.iterator  
    let set = new Set().add('a').add('b').add('c');
    
    let [x,y] = set;
    // x='a'; y='b'
    
    let [first, ...rest] = set;
    // first='a'; rest=['b','c'];
  • 확장 연산 자: 특정한 데이터 구조 가 Iterator 인 터 페 이 스 를 배치 하면 확장 연산 자 를 사용 하여 배열 로 전환 할 수 있 습 니 다
  •  //    ,          ,         Iterator        ,    。    ,            Iterator   ,            ,      
     //   
     var str = 'hello';
     [...str] //  ['h','e','l','l','o']
    
     //   
     let arr = ['b', 'c'];
     ['a', ...arr, 'd']
     // ['a', 'b', 'c', 'd']
  • yield: yield 뒤에 있 는 것 은 옮 겨 다 닐 수 있 는 구조 로 인터페이스의 옮 겨 다 니 는 인터페이스
  • 를 호출 합 니 다.
    let generator = function* () {
        yield 1;
        yield* [2,3,4];
        yield 5;
    };
    
    var iterator = generator();
    
    iterator.next() // { value: 1, done: false }
    iterator.next() // { value: 2, done: false }
    iterator.next() // { value: 3, done: false }
    iterator.next() // { value: 4, done: false }
    iterator.next() // { value: 5, done: false }
    iterator.next() // { value: undefined, done: true }
  • 다른 장소: 배열 의 스 트 리밍 은 스 트 리밍 인 터 페 이 스 를 호출 하기 때문에 배열 을 매개 변수 로 받 아들 이 는 모든 장소 에서 스 트 리밍 인 터 페 이 스 를 호출 했다.
  • for...of
  • Array.from()
  • Map(),Set(),WeakMap(),WeakSet()
  • Promise.all()
  • Promise.race()

  • 문자열 의 Iterator 인터페이스
     //              ,     Iterator  
     var someString = "hi";
     typeof someString[Symbol.iterator]
     // "function"
    
     var iterator = someString[Symbol.iterator]();
    
     iterator.next()  // { value: "h", done: false }
     iterator.next()  // { value: "i", done: false }
     iterator.next()  // { value: undefined, done:true }
     //        Symbol.iterator  ,            
     var str = new String("hi");
    
    [...str] // ["h", "i"]
    
    str[Symbol.iterator] = function() {
      return {
        next: function() {
          if (this._first) {
            this._first = false;
            return { value: "bye", done: false };
          } else {
            return { done: true };
          }
        },
        _first: true
      };
    };
    //     str  Symbol.iterator      ,       (...)       bye,        hi
    [...str] // ["bye"]
    str // "hi"

    Iterator 인터페이스 와 Generator 함수
    Symbol. iterator 방법의 가장 간단 한 실현 은 Generator 함 수 를 사용 하 는 것 입 니 다.
    // Symbol.iterator            ,    yield              
    let myIterable = {
      [Symbol.iterator]: function* () {
        yield 1;
        yield 2;
        yield 3;
      }
    }
    [...myIterable] // [1, 2, 3]
    
    //            
    
    let obj = {
      * [Symbol.iterator]() {
        yield 'hello';
        yield 'world';
      }
    };
    
    for (let x of obj) {
      console.log(x);
    }
    // "hello"
    // "world"

    옮 겨 다 니 는 대상 의 return (), throw ()
    스 트 리밍 대상 은 next 방법 외 에 return 방법 과 throw 방법 도 있 습 니 다.옮 겨 다 니 는 대상 생 성 함 수 를 직접 쓰 면 next 방법 은 반드시 배치 해 야 합 니 다. return 방법 과 throw 방법 은 배치 여 부 를 선택 할 수 있 습 니 다.
    return 방법의 사용 장 소 는 for... of 순환 이 미리 종료 되면 return 방법 을 사용 합 니 다.대상 이 옮 겨 다 니 기 전에 자원 을 정리 하거나 방출 해 야 한다 면 return 방법 을 배치 할 수 있 습 니 다.
    //   readLinesSync            ,         ,    next  ,    return  
    function readLinesSync(file) {
      return {
        [Symbol.iterator]() {
          return {
            next() {
              return { done: false };
            },
            return() {
              file.close();
              return { done: true };
            }
          };
        },
      };
    }
    //        ,      return  
    //           ,    return  ,      
    for (let line of readLinesSync(fileName)) {
      console.log(line);
      break;
    }
    
    //     return        ,     
    for (let line of readLinesSync(fileName)) {
      console.log(line);
      throw new Error();
    }

    주: return 방법 은 대상 을 되 돌려 야 합 니 다. 이것 은 Generator 규격 이 결정 하 는 throw 방법 입 니 다. 주로 Generator 함수 에 맞 춰 사용 합 니 다. 일반적인 스 트 리밍 대상 은 이 방법 을 사용 하지 않 습 니 다.
    for... of circle 순환
  • 배열 과 배열 의 데이터 구 조 를 순환 할 수 있다
  • for... of 순환 내부 호출 은 데이터 구조의 Symbol. iterator 방법
  • 순환 으로 키 를 얻 을 수 있 습 니 다
  •  var arr = ['a', 'b', 'c', 'd'];
    
     for (let a in arr) {
       console.log(a); // 0 1 2 3
     }
    
     for (let a of arr) {
       console.log(a); // a b c d
     }
  • 배열 의 달력 인 터 페 이 스 는 디지털 색인 이 있 는 속성 만 되 돌려 줍 니 다
  • 배열
    배열 원생 은 iterator 인터페이스 (즉, Symbol. iterator 속성 을 기본 으로 배치 합 니 다) 를 갖 추고 있 습 니 다. for.. of 순환 은 본질 적 으로 이 인터페이스 에서 발생 하 는 스 트 리밍 기 를 호출 하 는 것 입 니 다.
    //    obj     arr Symbol.iterator  ,  obj for...of  ,    arr       
    const arr = ['red', 'green', 'blue'];
    
    for(let v of arr) {
      console.log(v); // red green blue
    }
    
    const obj = {};
    obj[Symbol.iterator] = arr[Symbol.iterator].bind(arr);
    
    for(let v of obj) {
      console.log(v); // red green blue
    }

    for... of 순환 은 배열 인 스 턴 스 를 대체 할 수 있 는 foreach 방법 입 니 다.
    const arr = ['red', 'green', 'blue'];
    arr.forEach(function (element, index) {
      console.log(element); // red green blue
      console.log(index);   // 0 1 2
    });

    JavaScript 기 존의 for... in 순환, 대상 의 키 만 얻 을 수 있 습 니 다. 키 값 을 직접 가 져 올 수 없습니다.
    var arr = ['a', 'b', 'c', 'd'];
    
    for (let a in arr) {
      console.log(a); // 0 1 2 3
    }
    
    for (let a of arr) {
      console.log(a); // a b c d
    }

    주: for... of 순환 호출 스 트 리밍 인터페이스, 배열 의 스 트 리밍 인 터 페 이 스 는 디지털 색인 이 있 는 속성 만 되 돌려 줍 니 다.
    let arr = [3, 5, 7];
    arr.foo = 'hello';
    
    for (let i in arr) {
      console.log(i); // "0", "1", "2", "foo"
    }
    
    for (let i of arr) {
      console.log(i); //  "3", "5", "7"
    }

    for... 의 장점:
  • 같은 for... in 과 같은 간결 한 문법 을 가지 고 있 지만 for... in 의 단점 이 없다
  • foreach 방법 과 달리 break, contine, return 과 함께 사용 할 수 있 습 니 다
  • 옮 겨 다 니 는 모든 데이터 구조 통일 조작 인터페이스
  • 를 제공 합 니 다.
    단점
  • 배열 의 키 이름 은 숫자 이지 만 for... in 순환 은 문자열 을 키 이름 으로 '0', '1'
  • for... in 순환 은 디지털 키 이름 뿐만 아니 라 수 동 으로 추 가 된 다른 키 도 옮 겨 다 니 며 원형 체인 의 키
  • 도 포함한다.
  • 어떤 경우, for... in 순환 은 키 이름
  • 을 임의의 순서 로 옮 겨 다 닙 니 다.
    Set 와 Map 구조
    Set 와 Map 구조 도 원생 Iterator 인터페이스 가 있어 for... of 순환 을 직접 사용 할 수 있 습 니 다.
    var engines = new Set(["Gecko", "Trident", "Webkit", "Webkit"]);
    for (var e of engines) {
      console.log(e);
    }
    // Gecko
    // Trident
    // Webkit
    
    var es6 = new Map();
    es6.set("edition", 6);
    es6.set("committee", "TC39");
    es6.set("standard", "ECMA-262");
    for (var [name, value] of es6) {
      console.log(name + ": " + value);
    }
    // edition: 6
    // committee: TC39
    // standard: ECMA-262

    주:
  • 옮 겨 다 니 는 순 서 는 각 구성원 이 데이터 구조 에 추 가 된 순서
  • 이다.
  • Set 구 조 는 한 개의 값 을 되 돌려 주 고 Map 구 조 는 한 개의 배열 을 되 돌려 줍 니 다. 이 배열 의 두 구성원 은 현재 Map 구성원 의 키 이름과 키
  • 입 니 다.
    let map = new Map().set('a', 1).set('b', 2);
    for (let pair of map) {
      console.log(pair);
    }
    // ['a', 1]
    // ['b', 2]
    
    for (let [key, value] of map) {
      console.log(key + ' : ' + value);
    }
    // a : 1
    // b : 2

    계산 생 성 된 데이터 구조
    일부 데이터 구 조 는 기 존의 데이터 구 조 를 바탕 으로 계산 하여 생 성 된 것 이다.예 를 들 어 ES6 의 배열, Set, Map 은 모두 다음 과 같은 세 가지 방법 을 배 치 했 고 호출 한 후에 모두 옮 겨 다 니 는 대상 으로 돌아 갔다.
  • entries () 는 옮 겨 다 니 는 대상 을 되 돌려 줍 니 다. [키 이름, 키 값] 으로 구 성 된 배열 은 배열 에 대해 키 이름 은 색인 값 입 니 다.Set 에 대해 서 는 키 이름과 키 가 같 습 니 다.Map 구조의 Iterator 인 터 페 이 스 는 기본적으로 entries 방법
  • 을 호출 합 니 다.
  • keys () 는 모든 키 이름
  • 을 옮 겨 다 니 는 데 사용 되 는 옮 겨 다 니 는 대상 을 되 돌려 줍 니 다.
  • values () 는 모든 키 를 옮 겨 다 니 는 데 사용 되 는 옮 겨 다 니 는 대상 을 되 돌려 줍 니 다
  • 이 세 가지 방법 을 호출 한 후 생 성 된 스 트 리밍 대상 은 모두 생 성 된 데이터 구 조 를 계산 하 는 것 이다.
    let arr = ['a', 'b', 'c'];
    for (let pair of arr.entries()) {
      console.log(pair);
    }
    // [0, 'a']
    // [1, 'b']
    // [2, 'c']

    배열 과 유사 한 대상
    유사 한 배열 의 대상 은 여러 가지 유형 을 포함한다.
    
    //    
    let str = "hello";
    
    for (let s of str) {
      console.log(s); // h e l l o
    }
    
    // DOM NodeList  
    let paras = document.querySelectorAll("p");
    
    for (let p of paras) {
      p.classList.add("test");
    }
    
    // arguments  
    function printArgs() {
      for (let x of arguments) {
        console.log(x);
      }
    }
    printArgs('a', 'b');
    // 'a'
    // 'b'
    

    문자열 에 있어 for... of 순환 은 32 비트 UTF - 16 문 자 를 정확하게 식별 하 는 특징 이 있 습 니 다.
    for (let x of 'a\uD83D\uDC0A') {
      console.log(x);
    }
    // 'a'
    // '\uD83D\uDC0A'

    모든 유사 한 배열 의 대상 이 Iterator 인 터 페 이 스 를 가지 고 있 는 것 은 아 닙 니 다. 간단 한 해결 방법 은 Array. from 방법 으로 배열 로 바 꾸 는 것 입 니 다.
    let arrayLike = { length: 2, 0: 'a', 1: 'b' };
    
    //   
    for (let x of arrayLike) {
      console.log(x);
    }
    
    //   
    for (let x of Array.from(arrayLike)) {
      console.log(x);
    }

    대상
    일반적인 대상 에 대해 for... of 구 조 는 직접 사용 할 수 없고 오류 가 발생 할 수 있 습 니 다. Iterator 인 터 페 이 스 를 배치 해 야 사용 할 수 있 습 니 다.하지만, for... in 순환 은 키 이름 을 옮 겨 다 닐 수 있 습 니 다.
    let es6 = {
      edition: 6,
      committee: "TC39",
      standard: "ECMA-262"
    };
    
    for (let e in es6) {
      console.log(e);
    }
    // edition
    // committee
    // standard
    
    for (let e of es6) {
      console.log(e);
    }
    // TypeError: es6[Symbol.iterator] is not a function

    하나의 해결 방법 은 Object. keys 방법 으로 대상 의 키 이름 을 배열 로 만 든 다음 이 배열 을 옮 겨 다 니 는 것 이다.
    for (var key of Object.keys(someObject)) {
      console.log(key + ': ' + someObject[key]);
    }

    또 다른 방법 은 Generator 함 수 를 사용 하여 대상 을 다시 포장 하 는 것 이다.
    function* entries(obj) {
      for (let key of Object.keys(obj)) {
        yield [key, obj[key]];
      }
    }
    
    for (let [key, value] of entries(obj)) {
      console.log(key, '->', value);
    }
    // a -> 1
    // b -> 2
    // c -> 3

    다른 문법 과 의 비교
    배열 의 경우 자바 스 크 립 트 는 여러 가지 문법 을 제공 합 니 다.가장 원시 적 인 문법 은 for 순환 이다
    //         
    for (var index = 0; index < myArray.length; index++) {
      console.log(myArray[index]);
    }

    따라서 배열 은 내 장 된 foreach 방법 을 제공 합 니 다.
    //          ,      forEach  ,break   return       
    myArray.forEach(function (value) {
      console.log(value);
    });

    for... in 순환 으로 배열 의 키 이름 을 옮 겨 다 닐 수 있 습 니 다.
    for (var index in myArray) {
      console.log(myArray[index]);
    }

    for... in 순환 의 몇 가지 단점:
  • 배열 의 키 이름 은 숫자 이지 만 for... in 순환 은 문자열 을 키 이름 으로 '0', '1'
  • for... in 순환 은 디지털 키 이름 뿐만 아니 라 수 동 으로 추 가 된 다른 키 도 옮 겨 다 니 며 원형 체인 의 키
  • 도 포함한다.
  • 어떤 경우, for... in 순환 은 키 이름
  • 을 임의의 순서 로 옮 겨 다 닙 니 다.
    한 마디 로 하면 for... in 순환 은 주로 대상 을 옮 겨 다 니 기 위해 설 계 된 것 으로 배열 에 적용 되 지 않 습 니 다.
    for... of 순환 은 위의 몇 가지 방법 에 비해 현저 한 장점 이 있 습 니 다.
    for (let value of myArray) {
      console.log(value);
    }
  • 같은 for... in 과 같은 간결 한 문법 을 가지 고 있 지만 for... in 의 단점 이 없다
  • foreach 방법 과 달리 break, contine, return 과 함께 사용 할 수 있 습 니 다
  • 옮 겨 다 니 는 모든 데이터 구조 통일 조작 인터페이스
  • 를 제공 합 니 다.
    //    break   ,  for...of  
    //              1000   。        1000,    break    for...of  
    for (var n of fibonacci) {
      if (n > 1000)
        break;
      console.log(n);
    }

    좋은 웹페이지 즐겨찾기