blog

자바스크립트 Iterator 개념 정리

  • Array.from
  • Javascript
  • iterable
  • iterator
  • Javascript에서의 Interface, iterator 객체의 개념에 대해서 살펴보자. 😊

    Interface

    1. 인터페이스란 사양에 맞는 값과 연결된 속성키의 셋트
    2. 어떤 Object라도 인터페이스의 정의를 충족시킬 수 있다.
    3. 하나의 Object는 여러 개의 인터페이스를 충족할 수 있다.

    An 'interface' is a set of property keys whose associated values match a specific specification. Any object that provides all the properties as described by an interface's specification conforms to that interface. An interface is not represented by a distinct object. There may be many separately implemented objects that conform to any interface. An individual object may conform to multiple interfaces.

    🗒스펙문서 (https://tc39.es/ecma262/#sec-iteration)

    예를 들어, Test Interface 정의를 test라는 키를 갖고, 값으로 문자열을 받아 Boolean을 리턴하는 함수가 온다고 하자.

    {
    	test(str){return true;}
    }

    그럼 다음과 같이 간단한 Test Interface의 정의를 만족하는 객체를 만들 수 있을 것이다.

    Iterator Interface

    1. next라는 키를 갖는다.
    2. 값으로 인자를 받지 않고, IteratorResultObject를 반환하는 함수가 온다.
    3. IteratorResultObject는 value와 done이라는 key를 가지고 있다.
    4. done은 계속 반복할 수 있을지 없을지에 대한 Boolean값을 반환다.
    {
        next() {
          	return {value: 1, done: true};
        } 
    }

    Iterable Interface

    1. Symbol.iterator라는 키를 갖는다.
    2. 값으로 인자를 받지 않고, Iterator Object를 반환하는 함수가 온다.
    {
        [Symbol.iterator](){
        	return {
               next() {
                 return {value: 1, done: true};
               }
            }
        }
    }

    다음과 같은 예를 만들 수도 있음.

    const iter = {
      [Symbol.iterator]() {
        return this;
      },
      arr: [1, 2, 3, 4, 5],
      next() {
        return {
          done: this.arr.length === 0,
          value: this.arr.pop()
        };
      }
    };
    
    
    for (const item of iter) {
      console.log(item);
    }
    
    /*
    출력
    5
    4
    3
    2
    1
    */
    
    
    const iter = {
      [Symbol.iterator]() {
        return this;
      },
      arr: [1, 2, 3, 4, 5],
      next() {
        return {
          done: this.arr.length === 0,
          value: this.arr.pop()
        };
      }
    };
    
    const [a, ...b] = iter;
    console.log(a);
    
    /*
    출력
    5
    */
    
    

    iterable interface의 정의를 충족 시키면 다음과 같이 array destructuring같은 언어 스펙을 사용할 수 있다.

    for ~ of 의 루프대신 직접 호출을 통한 반복

    // 문자열도 iterable이다.
    const str = '문자열입니다.';
    
    const iterator = str[Symbol.iterator]();
    
    while(true) {
      const iteratorResultObject = iterator.next();
      if (iteratorResultObject.done) break;
      console.log(iteratorResultObject.value);
    }

    이터러블과 유사 배열

    비슷해 보이지만 아주 다른 용어 두 가지가 있다. 헷갈리지 않으려면 두 용어를 잘 이해하고 있어야 한다.

    • 이터러블(iterable)은 위에서 설명한 바와 같이 메서드 Symbol.iterator가 구현된 객체임.
    • 유사 배열(array-like)은 인덱스와 length 프로퍼티가 있어서 배열처럼 보이는 객체임.

    Array.from

    범용 메서드 Array.from는 이터러블이나 유사 배열을 받아 진짜 Array를 만들어준다. 이 과정을 거치면 이터러블이나 유사 배열에 배열 메서드를 사용할 수 있다.

    
    // 유사 배열
    const arrayLike = {
      0: 1,
      1: 2,
      length: 2
    };
    
    console.log(Array.from(arrayLike).pop());
    
    // iterable
    const iter = {
      [Symbol.iterator]() {
        return this;
      },
      arr: [1, 2, 3, 4, 5],
      next() {
        return {
          done: this.arr.length === 0,
          value: this.arr.pop()
        };
      }
    };
    
    
    /*
    pop을 하면서 반복하는 iterable 객체이므로
    Array.from(iter)
     = [5,4,3,2,1]
    */
    
    console.log(Array.from(iter).pop());
    
    // 출력
    // 2
    // 1
    
    

    출처

    코드스피츠
    https://ko.javascript.info/iterable

    Top
    Copyright©2022 Klog(blackbell) all right reserved