Iterator 와 for... of 순환

8350 단어
Iterator (달력)
콘 셉 트
'집합' 을 나타 내 는 데이터 구 조 는 주로 기 존의 ArrayObject, ES6 가 증가 한 MapSet 이다. 모든 서로 다른 데이터 구 조 를 처리 하 는 통 일 된 인터페이스 체제 가 필요 하 다. 모든 데이터 구 조 는 Iterator 인 터 페 이 스 를 배치 하면 스 트 리밍 작업 (즉, 이 데이터 구 조 를 순서대로 처리 하 는 모든 구성원) 의 역할 은 주로 세 가지 가 있다.
  • 각종 데이터 구조 에 통일 되 고 간편 한 액세스 인터페이스 제공
  • 데이터 구조의 구성원 을 특정한 순서에 따라 배열 할 수 있 게 한다
  • 편리 한 사용 for...of 사용 원 리 는 주로 하나의 포인터 대상 을 만 들 고 현재 데이터 구조의 시작 위 치 를 가리 키 며 포인터 대상 next 방법 을 계속 호출 하 는 것 이다. 매번 호출 next 방법 을 사용 할 때마다 데이터 구조의 현재 구성원 의 정 보 를 되 돌려 준다. 구체 적 으로 말 하면 valuedone 두 가지 속성 을 포함 하 는 대상 을 되 돌려 주 는 것 이다. 그 중에서 value속성 은 현재 구성원 의 값 입 니 다. done 속성 은 불 값 입 니 다. 옮 겨 다 니 는 것 이 끝 났 는 지 여 부 를 표시 합 니 다
  • 기본 Iterator 인터페이스
    하나의 데이터 구조 가 Iterator 인 터 페 이 스 를 배치 하면 우 리 는 이러한 데이터 구 조 를 '옮 겨 다 닐 수 있 는' ES6 규정 이 라 고 부 릅 니 다. 기본 Iterator 인 터 페 이 스 는 데이터 구조의 Symbol.iterator 속성 에 배치 되 어 있 습 니 다. Symbol.iterator 익숙 한 것 자체 가 하나의 함수 입 니 다. 바로 현재 데이터 구조의 기본 적 인 옮 겨 다 니 기 생 성 함수 입 니 다. 이 함 수 를 실행 하면 옮 겨 다 니 는 기 기 를 되 돌려 줍 니 다. 속성 명 Symbol.iterator 에 대해 서 는.이것 은 표현 식 입 니 다. Symbol 대상 의 iterator 속성 을 되 돌려 줍 니 다. 이것 은 미리 정 의 된 형식 Symbol 의 특수 값 이기 때문에 괄호 안에 넣 어야 합 니 다.
    const obj = {
      [Symbol.iterator] : function () {
        return {
          next: function () {
            return {
              value: 1,
              done: true
            };
          }
        };
      }
    };
    

    ES6 의 일부 데이터 구 조 는 원생 이 Iterator 인 터 페 이 스 를 갖 추고 있다. 즉, 어떠한 처리 도 하지 않 아 도 for...of 원생 이 Iterator 인 터 페 이 스 를 갖 춘 데이터 구 조 는 다음 과 같다.
  • Array
  • Map
  • Set
  • String
  • TypedArray
  • 함수 의 arguments 대상
  • NodeList 대상
  • 아래 의 예 는 배열 의 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 }
    

    원생 배치 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
    }
    

    다음은 대상 에 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.prototype[Symbol.iterator] = Array.prototype[Symbol.iterator];
    //   
    NodeList.prototype[Symbol.iterator] = [][Symbol.iterator];
    
    [...document.querySelectorAll('div')] //      
    

    일반 대상 에 배열 을 배치 하 는 Symbol.iterator 방법 은 효과 가 없습니다.
    Iterator 인터페이스 호출 장소
    Iterator 인 터 페 이 스 를 기본 으로 호출 하 는 경우 가 있 습 니 다.
  • 디 스 플레이 할당 값 이 배열 과 Set 디 스 플레이 에 대해 디 스 플레이 할당 을 할 때
  • 확장 연산 자 는 특정한 데이터 구조 가 Iterator 인 터 페 이 스 를 배치 하면 확장 연산 자 를 사용 하여 배열
  • 로 전환 할 수 있다.
  • yield*
  • 다른 장소 에 서 는 배열 의 스 트 리밍 이 스 트 리밍 인 터 페 이 스 를 호출 해 야 하기 때문에 배열 을 매개 변수 로 받 아들 이 는 모든 장소 에서 스 트 리밍 인 터 페 이 스 를 호출 했다.
  • for...of
  • Array.from
  • Map,Set,WeakMap,WeakSet
  • Promise.all
  • Promise.race


  • Iterator 인터페이스 와 Generator 함수Symbol.iterator 방법의 가장 간단 한 실현 은 역시 Generator 함 수 를 사용 하 는 것 이다.
    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 ()Symbol.iterator 방법 과 return 방법의 배치 여 부 를 선택 할 수 있 는 throw 방법의 사용 장 소 는 return 순환 이 앞 당 겨 탈퇴 (보통 오류 때 문 이거 나 for...of 문구 나 break 문구 가 있 으 면 continue 방법 을 사용 하 는 것 이다. 만약 에 한 대상 이 옮 겨 다 니 기 전에 자원 을 정리 하거나 방출 해 야 한다 면 배치 return 방법 을 사용 할 수 있다.
    function readLinesSync(file) {
      return {
        [Symbol.iterator]() {
          return {
            next() {
              return { done: false };
            },
            return() {
              file.close();
              return { done: true };
            }
          };
        },
      };
    }
    

    메모: return 방법 은 대상 return 방법 을 되 돌려 야 합 니 다. 주로 Generator 함수 와 결합 하여 사용 해 야 합 니 다. 일반적인 스 트 리밍 대상 은 이 방법 을 사용 하지 않 습 니 다.
    for... of circle 순환
    콘 셉 트
    도입 throw 순환 은 모든 데이터 구 조 를 옮 겨 다 니 는 통 일 된 방법 으로 자바 스 크 립 트 기 존의 for...of 순환 으로 대상 의 키 이름 만 얻 을 수 있 고 키 값 을 직접 얻 을 수 없습니다. ES6 제공 for...in 순환 은 키 값 for...of 순환 으로 옮 겨 다 니 며 연결 구 를 호출 할 수 있 습 니 다. 배열 의 옮 겨 다 니 는 인 터 페 이 스 는 디지털 색인 이 있 는 속성 만 되 돌려 줍 니 다. 이 점 은 for...of 순환 과 다 릅 니 다.
    Set 와 Map 구조
    Set 구조 와 Map 구 조 를 옮 겨 다 니 며 주의 하 는 부분 은 두 가지 가 있 습 니 다. 우선, 옮 겨 다 니 는 순 서 는 각 구성원 이 데이터 구조 에 추 가 된 순서 입 니 다. 그 다음 에 Set 구 조 는 한 개의 값 을 되 돌려 주 고 Map 구 조 는 한 개의 배열 을 되 돌려 줍 니 다.
    계산 생 성 된 데이터 구조
    ES6 의 배열, Set, Map 은 모두 다음 과 같은 세 가지 방법 을 배 치 했 고 호출 후 모두 옮 겨 다 니 는 대상 으로 돌아 갔다.
  • for...in: 스 트 리밍 대상 은 스 트 리밍 entries() 으로 구 성 된 배열 입 니 다. 배열 에 대해 서 는 키 이름 이 색인 값 입 니 다.Set 에 대해 서 는 키 이름과 키 가 같 습 니 다.Map 구조의 Iterator 인 터 페 이 스 는 기본적으로 이 방법 을 호출 합 니 다.
  • [ , ]
  • keys()

  • 배열 과 유사 한 대상
    문자열 에 있어 서 values() 는 32 비트 UTF - 16 문 자 를 정확하게 식별 하여 사용 할 수 있 는 for...of 방법 으로 유사 한 배열 의 대상 을 배열 로 바 꾸 는 특징 이 있다.
    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);
    }
    

    대상
    일반적인 대상 에 대해 서 는 Array.from 구 조 를 직접 사용 할 수 없 으 며, Iterator 인 터 페 이 스 를 배치 해 야 해결 방법 을 사용 할 수 있 습 니 다. for...of 방법 으로 대상 의 키 이름 을 배열 로 만 드 는 것 입 니 다.
    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
    

    다른 문법 과 의 비교Object.keys 순환 을 중간 에 뛰 어 넘 지 못 하 는 단점 forEach 은 몇 가지 가 있 습 니 다. 1. 문자열 을 키 이름 으로 '0', '1', '2' 등 2. 배열 의 키 뿐만 아니 라 수 동 으로 추 가 된 다른 키 도 옮 겨 다 니 고 심지어 원형 체인 의 키 도 포함 합 니 다. 어떤 경우 에는 임의의 순서 로 키 이름 for...in 을 옮 겨 다 니 는 것 이 현저 한 장점 이 있 습 니 다. 1. for...of 그런 단점 이 없습니다. 2. for...in 방법 과 다 릅 니 다.이 는 forEach 와 함께 사용 할 수 있 습 니 다. 3. 모든 데이터 구 조 를 옮 겨 다 니 는 통 일 된 조작 인 터 페 이 스 를 제공 합 니 다.

    좋은 웹페이지 즐겨찾기