ES6 Iterator 와 for... of 순환

10578 단어 es6iteratorfor 순환
Iterator 의 개념
스 트 리밍 기 (Iterator) 는 다양한 데이터 구조 에 통 일 된 접근 체 제 를 제공 하 는 인터페이스 이다.모든 데이터 구 조 는 Iterator 인 터 페 이 스 를 배치 하면 옮 겨 다 니 기 작업 을 완성 할 수 있 습 니 다 (즉, 이 데이터 구 조 를 순서대로 처리 하 는 모든 구성원).
Iterator 의 역할 은 세 가지 가 있 습 니 다.
  • 하 나 는 각종 데이터 구 조 를 위해 통일 되 고 간편 한 방문 인 터 페 이 스 를 제공 하 는 것 이다.
  • 둘째, 데이터 구조의 구성원 들 이 특정한 순서에 따라 배열 할 수 있 도록 하 는 것 이다.
  • 세 번 째 는 ES6 가 새로운 옮 겨 다 니 는 명령 for... of 순환 을 만 들 었 고 Iterator 인 터 페 이 스 는 주로 for... of 소 비 를 제공 합 니 다.

  • Iterator 의 옮 겨 다 니 는 과정 은 다음 과 같 습 니 다.
  • 포인터 대상 을 만 들 고 현재 데이터 구조의 시작 위 치 를 가리킨다.즉, 옮 겨 다 니 는 대상 은 본질 적 으로 지침 대상
  • 이다.
  • 포인터 대상 을 처음 호출 하 는 next 방법 으로 데이터 구조의 첫 번 째 구성원
  • 을 가리 킬 수 있 습 니 다.
  • 두 번 째 포인터 대상 을 호출 하 는 next 방법 은 데이터 구조의 두 번 째 구성원
  • 을 가리킨다.
  • 데이터 구조의 끝 위 치 를 가리 킬 때 까지 포인터 대상 의 next 방법 을 계속 호출 합 니 다.

  • 매번 next 방법 을 호출 할 때마다 데이터 구조의 현재 구성원 의 정 보 를 되 돌려 줍 니 다.구체 적 으로 말 하면 value 와 done 두 속성 을 포함 하 는 대상 을 되 돌려 주 는 것 이다.그 중에서 value 속성 은 현재 구성원 의 값 입 니 다. done 속성 은 불 값 입 니 다. 옮 겨 다 니 는 것 이 끝 났 는 지 여 부 를 표시 합 니 다.
    다음은 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};
        }
      };
    }

    위 코드 는 MakeIterator 함 수 를 정의 합 니 다. 이것 은 스 트 리밍 기 생 성 함수 입 니 다. 스 트 리밍 기 대상 을 되 돌려 주 는 역할 을 합 니 다.배열 [a ',' b '] 에서 이 함 수 를 실행 하면 이 배열 의 스 트 리밍 대상 (즉 포인터 대상) it 로 돌아 갑 니 다.
    Iterator 는 인터페이스 규격 을 데이터 구조 에 만 추가 하기 때문에 스 트 리밍 기 는 그 데이터 구조 와 실제 적 으로 분 리 된 것 으로 데이터 구조 에 대응 하지 않 는 스 트 리밍 기 대상 을 작성 하거나 스 트 리밍 기 대상 으로 데이터 구 조 를 모 의 할 수 있 습 니 다.다음은 무한 실행 중인 달력 대상 의 예 입 니 다.
    var it = idMaker();
    
    it.next().value // '0'
    it.next().value // '1'
    it.next().value // '2'
    // ...
    
    function idMaker() {
      var index = 0;
    
      return {
        next: function() {
          return {value: index++, done: false};
        }
      };
    }

    위의 예 에서 스 트 리밍 기 생 성 함수 idMaker 는 스 트 리밍 대상 (즉 포인터 대상) 을 되 돌려 줍 니 다.그러나 대응 하 는 데이터 구조 가 없 거나 옮 겨 다 니 는 대상 이 스스로 데이터 구 조 를 묘사 했다.
    TypeScript 의 쓰기 방법 을 사용 하면 스 트 리밍 인터페이스 (Iterable), 포인터 대상 (Iterator) 과 next 방법 으로 값 을 되 돌려 주 는 규격 은 다음 과 같 습 니 다.
    interface Iterable {
      [Symbol.iterator]() : Iterator,
    }
    
    interface Iterator {
      next(value?: any) : IterationResult,
    }
    
    interface IterationResult {
      value: any,
      done: boolean,
    }

    기본 Iterator 인터페이스
    for... of 순환 을 사용 하여 특정한 데이터 구 조 를 옮 겨 다 닐 때 이 순환 은 자동 으로 Iterator 인 터 페 이 스 를 찾 습 니 다.하나의 데이터 구조 가 Iterator 인 터 페 이 스 를 배치 하면 우 리 는 이러한 데이터 구 조 를 '옮 겨 다 닐 수 있 는' (iterable) 이 라 고 부른다.
    ES6 에 서 는 기본 Iterator 인터페이스 가 데이터 구조의 Symbol. iterator 속성 에 배치 되 어 있 거나, 하나의 데이터 구 조 는 Symbol. iterator 속성 만 있 으 면 '옮 겨 다 닐 수 있 는' 것 으로 볼 수 있 습 니 다. Symbol. iterator 속성 자 체 는 하나의 함수 이 며, 현재 데이터 구조 에서 기본 적 인 스 트 리밍 기 생 성 함수 입 니 다. 이 함 수 를 실행 하면 스 트 리밍 기 를 되 돌려 줍 니 다.
    const obj = {
      [Symbol.iterator] : function () {
        return {
          next: function () {
            return {
              value: 1,
              done: true
            };
          }
        };
      }
    };

    위 코드 에서 대상 obj 는 옮 겨 다 닐 수 있 는 (iterable) 입 니 다. Symbol. iterator 속성 이 있 기 때 문 입 니 다. 이 속성 을 실행 하면 옮 겨 다 니 는 대상 을 되 돌려 줍 니 다. 이 대상 의 근본 적 인 특징 은 next 방법 입 니 다. next 방법 을 호출 할 때마다 현재 구성원 을 대표 하 는 정보 대상 을 되 돌려 줍 니 다. value 와 done 두 속성 이 있 습 니 다.
    ES6 의 일부 데이터 구 조 는 원래 Iterator 인터페이스 (예 를 들 어 배열) 를 갖 추고 있 습 니 다. 즉, 어떠한 처리 도 하지 않 아 도 for.. of 순환 으로 옮 겨 다 닐 수 있 습 니 다. 이 데이터 구 조 는 원래 Symbol. iterator 속성 을 배 치 했 기 때 문 입 니 다. 다른 데이터 구 조 는 (예 를 들 어 대상) 이 없 기 때 문 입 니 다.. Symbol. iterator 속성 이 배 치 된 데이터 구 조 를 옮 겨 다 니 는 인터페이스 라 고 합 니 다. 이 인 터 페 이 스 를 호출 하면 옮 겨 다 니 는 대상 을 되 돌려 줍 니 다.
    원생 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 }

    위의 코드 에서 변수 arr 는 하나의 배열 입 니 다. 원생 은 스 트 리밍 인터페이스 가 있 고 arr 의 Symbol. iterator 속성 에 배치 되 어 있 습 니 다. 따라서 이 속성 을 호출 하면 스 트 리밍 대상 을 얻 을 수 있 습 니 다.
    대상 이 for... of 순환 호출 가능 한 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 인 터 페 이 스 를 배치 하 는 쓰기 입 니 다. Symbol. iterator 속성 은 함수 에 대응 합 니 다. 실행 후 현재 대상 의 스 트 리밍 대상 으로 돌아 갑 니 다.
    유사 한 배열 의 대상 (수치 키 이름과 length 속성 이 존재 함) 에 대해 Iterator 인 터 페 이 스 를 배치 하 는 간단 한 방법 은 Symbol. iterator 방법 으로 배열 의 Iterator 인 터 페 이 스 를 직접 참조 하 는 것 입 니 다.
    NodeList.prototype[Symbol.iterator] = Array.prototype[Symbol.iterator];
    //   
    NodeList.prototype[Symbol.iterator] = [][Symbol.iterator];
    
    [...document.querySelectorAll('div')] //      

    NodeList 대상 은 배열 과 유사 한 대상 입 니 다. 원래 인 터 페 이 스 를 옮 겨 다 니 며 직접 옮 겨 다 닐 수 있 습 니 다. 위의 코드 에 서 는 인 터 페 이 스 를 배열 의 Symbol. iterator 속성 으로 바 꾸 었 습 니 다. 아무런 영향 이 없 음 을 볼 수 있 습 니 다.
    다음은 다른 배열 과 유사 한 대상 이 배열 의 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 인터페이스 호출 장소
    1. 할당 해제
    배열 과 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'];

    2. 확장 연산 자
    확장 연산 자 (...) 도 기본 Iterator 인 터 페 이 스 를 호출 합 니 다.
    //   
    var str = 'hello';
    [...str] //  ['h','e','l','l','o']
    
    //   
    let arr = ['b', 'c'];
    ['a', ...arr, 'd']
    // ['a', 'b', 'c', 'd']

    실제로 이 는 하나의 데이터 구조 가 Iterator 인 터 페 이 스 를 배치 하면 확장 연산 자 를 사용 하여 배열 로 전환 할 수 있 는 간편 한 메커니즘 을 제공 했다.
    3. 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 }

    4. 다른 장소
    배열 의 스 트 리밍 은 스 트 리밍 인 터 페 이 스 를 호출 하기 때문에 배열 을 매개 변수 로 받 아들 이 는 모든 경우 스 트 리밍 인 터 페 이 스 를 호출 합 니 다. 다음은 예 입 니 다.
  • for...of
  • Array.from()
  • Map (), Set (), WeakMap (), WeakSet () (예 를 들 어 new Map (['a', 1], ['b', 2])
  • 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 }

    Iterator 인터페이스 와 Generator 함수
    Symbol. iterator 방법의 가장 간단 한 실현:
    var myIterable = {};
    
    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 순환 이 앞 당 겨 종료 되면 (오류 가 발생 하거나 break 문 이나 continue 문 이 있 기 때 문) return 방법 을 사용 합 니 다. 대상 이 옮 겨 다 니 기 전에 자원 을 정리 하거나 방출 해 야 한다 면 return 방법 을 배치 할 수 있 습 니 다.
    function readLinesSync(file) {
      return {
        next() {
          return { done: false };
        },
        return() {
          file.close();
          return { done: true };
        },
      };
    }

    위의 코드 에서 함수 readLinesSync 는 파일 대상 을 매개 변수 로 받 아들 여 스 트 리밍 대상 을 되 돌려 줍 니 다. 그 중에서 next 방법 을 제외 하고 return 방법 도 배 치 했 습 니 다. 아래 세 가지 경우 모두 return 방법 을 실행 합 니 다.
    //    
    for (let line of readLinesSync(fileName)) {
      console.log(line);
      break;
    }
    
    //    
    for (let line of readLinesSync(fileName)) {
      console.log(line);
      continue;
    }
    
    //    
    for (let line of readLinesSync(fileName)) {
      console.log(line);
      throw new Error();
    }

    위의 코드 에 서 는 상황 이 출력 파일 의 첫 줄 이후 return 방법 을 실행 하여 이 파일 을 닫 습 니 다. 상황 2 출력 모든 줄 이후 return 방법 을 실행 하여 이 파일 을 닫 습 니 다. 상황 3 은 return 방법 을 실행 하여 파일 을 닫 은 후에 오 류 를 던 집 니 다.
    return 방법 은 대상 을 되 돌려 야 합 니 다. 이것 은 Generator 규격 에 의 해 결 정 된 것 입 니 다.
    throw 방법 은 주로 Generator 함수 에 맞 춰 사용 되 며, 일반적인 스 트 리밍 대상 은 이 방법 을 사용 하지 않 습 니 다.

    좋은 웹페이지 즐겨찾기