[JS] #3 Iteration

개요

이터레이션(Iteration): 반복

  • for( ) 문의 반복 개념과 차이가 있습니다.
    const list = [10, 20];
    for (let value of list) {
      console.log(value);
    };
    // 10
    // 20
    const obj = list[Symbol.iterator]();
    console.log(obj.next());
    console.log(obj.next());
    console.log(obj.next());
    // {value: 10, done: false}
    // {value: 20, done: false}
    // {value: undefined, done: true}

이터레이션을 위한 프로토콜(protocol)필요
ex: 통신 프로토콜(규약) - 데이터 송수신 프로토콜 정의

즉, 이터레이션은 프로토콜을 가지고 있으며 프로토콜에 따라 이터레이션을 수행합니다.

프로토콜이 구문과 빌트인이 아니므로 프로토콜에 맞으면 이터레이션이 가능합니다.

이터레이션 프로토콜

  • 이터레이션 프로토콜(규약)은 오브젝트가 이터레이션 할 수 있는 구조 + 이터레이션 함수를 가지고 있어야 한다는 것 입니다.
    • [10, 20]은 가능, 100은 불가능
  • 이터레이션 프로토콜 구분
    • 이터러블(iterable)프로토콜
      • 반복 가능해야하고
    • 이터레이터(iterator)프로토콜
      • 반복 가능한 오브젝트를 이터레이터 오브젝트로 만드는 프로토콜

개발자 코드로 프로토콜을 맞추면

  • 이터레이션 할 수 없는 오브젝트를 이터레이션 할 수 있도록 만들 수도 있습니다.

이터러블

이터러블 프로토콜

const list = [10, 20];
console.log(list[Symbol.iterator]);
// function values(){ [native code] }

오브젝트가 반복 가능한 구조이어야 하며 Symbol.iterator를 가지고 있는 것 입니다.

아래의 빌트인 오브젝트는 디폴트로 이터러블 프로토콜이 있습니다. 즉, Symbol.iterator를 가지고 있습니다.

Array, Argument, String, TypedArray, Map, Set, DOM NodeList

이터러블 오브젝트

  • 이터러블 오브젝트
    • 이터러블 프로토콜을 가지고 있는 오브젝트
    • 반복 구조, Symbol.iterator()
    • 스펙에서는 @@iterator()로 표기합니다.
  • 자체 오브젝트에는 없지만
    • 이터러블 오브젝트를 상속받아도 됩니다.
    • 즉, prototype chain(__proto__)에 있으면 됩니다.
    • 예를 들어, Array 오브젝트를 상속받으면 이터러블 오브젝트가 됩니다.
const list = [10, 20];
console.log(list[Symbol.iterator]);
// function values(){ [native code] }
const obj = {one: 10, two: 20};
console.log(obj[Symbol.iterator]);
// undefined

⇒ [ ] 리터럴로 생성한 list에 Symbol.iterator가 있기에 Array는 이터러블 오브젝트 입니다.
⇒ { } 리터럴로 생성한 obj에 Symbol.iterator가 없기에 Object는 이터러블 오브젝트가 아닙니다.
⇒ for문의 반복과 이터레이션이 차이가 있듯이 for-in의 열거와 이터레이션은 차이가 있습니다.
obj를 열거는 가능하지만, 이터레이션은 불가능합니다.

이터러블 오브젝트 구조


list의 scope를 확인하면 __proto__가 있고 이를 펼치면 Array 오브젝트의 메소드가 나열됩니다.

이를 살펴보면 Symbol(Symbol.iterator)가 있습니다.
그렇기 때문에 Array 오브젝트는 이터러블 오브젝트입니다.

또한, Symbol(Symbol.iterator)를 펼치면 __proto__에 Function 오브젝트의 메소드가 연결되어 있기에 Symbol.iterator는 함수입니다. 그렇기에 호출할 수 있습니다.


이터레이터

이터레이터 프로토콜

값을 순서대로 생성하는 방법(규약)

const list = [10, 20];
const obj = list[Symbol.iterator]();
console.log(obj.next());
console.log(obj.next());
console.log(obj.next());
// {value: 10, done: false}
// {value: 20, done: false}
// {value: undefined, done: true}
  • 이터레이터 오브젝트의 next()를 호출하면 이터레이터를 호출한다고도 합니다.
  • {value: 10, done: false}를 반환하는데, 여기서 value는 [10, 20]의 첫 번째 값이고 done: false는 이터레이터 상태입니다.
  • 여기서 done이 true가될 때까지 반복하며, 반복이 끝나면 {value: undefined, done: true}를 반환합니다. 이는 더이상 처리할 값이 없다는 것을 뜻하며 done: true는 이터레이터의 종료를 뜻합니다.

이터레이터 오브젝트

  • Symbol.iterator()를 호출하면
  • 이터레이터 오브젝트를 생성하여 반환합니다.
  • 이터레이터 오브젝트에는 next() 메소드가있습니다.
  • 생성한 오브젝트를 '이터레이터' 라고도 부릅니다.

  1. const list = [1, 2];
    • list.__proto__를 펼치면 Symbol(Symbol.iterator)가 있으므로 이터레이터 오브젝트를 만들 수 있습니다.
  2. const obj = list[Symbol.iterator]( );
    • 위 형태로 호출하면 이터레이터 오브젝트를 생성하여 반환합니다.
    • obj.__proto__를 펼치면 next() 메소드가 있습니다. next()가 있으므로 obj는 이터레이터 오브젝트입니다. (이터레이터 프로토콜)

정리

  • 이터러블 프로토콜
    • 이터레이션 할 수 있는 구조 + 이터레이션 함수 Symbol.iterator()
  • 이터러블 오브젝트
    1. 이터러블 프로토콜을 가지고 있는 오브젝트(ex. Array, DOM, Map, Set ... )
    2. 자체 오브젝트에는 없지만 이터러블 오브젝트를 상속받아 prototype chain(__proto__)에 있는 경우
  • 이터레이터 오브젝트
    • Symbol.iterator() 호출을 통해 생성하여 반환된 오브젝트
    • 이터레이터 프로토콜을 가지고 있는 오브젝트
  • 이터레이터 프로토콜
    • 생성된 이터레이터 오브젝트의 __proto__내 next() 메소드

개발자 코드로 프로토콜을 맞추면 이터레이션 할 수 없는 오브젝트를 이터레이션 할 수 있도록 만들 수도 있습니다.

좋은 웹페이지 즐겨찾기