본문 바로가기

JavaScript/AboutJS

[Javascript] Iterable, Iterator 프로토콜

 

자바스크립트의 이터러블(Iterable)과 이터레이터(Iterator) 프로토콜은 

객체의 순회 가능성을 정의하는 중요한 개념으로 ES6에 와서

for of 문으로 간단히 map set string 도 순회가 가능하도록 만들어준 개념입니다.

map set 은 배열처럼 set[0], set[1] 혹은 map[0], map[1] 으로 값을 접근 못하지만 for of 문을 돌 수 있는 이유가 

이터러블 이터레이터 프로토콜 때문입니다. 

 
아래의 커스텀 이터레이터 코드를 보면서 정의를 보면 이해가기가 조금 더 쉬워집니다.
  const iterable = {
    [Symbol.iterator](){
      let i = 3;
      return {
        next(){
          return i === 0 ? {value:undefined, done:true} : {value:i--, done:false};
        },
        // 이터러블도 이터레이터를 반환해야 well-formed 이터레이터가 될 수 있다
        [Symbol.iterator](){
          return this;
        }
      }
    }
  }
  let iter2 = iterable[Symbol.iterator]();
  for( const a of iter2) log(a); // 3,2,1
  1. 이터러블 (Iterable)
    • 이터러블은 반복 가능한 객체를 의미합니다.
    • [Symbol.iterator] (  ) 메서드를 가지고 있어야 합니다.( Symbol 은 객체의 키로 사용될 수 있다)
    • 이 메서드는 이터레이터를 반환해야 합니다.
    • 예: 배열, 문자열, Map, Set 등
  2. 이터레이터 (Iterator)
    • 이터레이터는 next() 메서드를 가진 객체입니다.
    • next() 메서드는 {value, done} 형태의 객체를 반환합니다.
    • value: 현재 요소의 값
    • done: 순회가 끝났는지를 나타내는 불리언 값
  3. 이터러블 프로토콜
    • 객체가 Symbol.iterator 메서드를 구현하면 이터러블이 됩니다.
    • 이 메서드는 이터레이터를 반환해야 합니다.
  4. 이터레이터 프로토콜
    • 객체가 next() 메서드를 구현하면 이터레이터가 됩니다.
    • next() 메서드는 {value, done} 객체를 반환해야 합니다.
  5. 이터러블의 장점
    • for...of 루프 사용 가능
    • 스프레드 연산자 (...) 사용 가능
    • 구조 분해 할당 가능
    • Array.from(), Map(), Set() 등의 생성자에서 사용 가능
   // 배열은 이터러블입니다
   const arr = [1, 2, 3];
   const iterator = arr[Symbol.iterator]();
   
   console.log(iterator.next()); // { value: 1, done: false }
   console.log(iterator.next()); // { value: 2, done: false }
   console.log(iterator.next()); // { value: 3, done: false }
   console.log(iterator.next()); // { value: undefined, done: true }

 

 

 

커스텀 이터러블 만들기

  const iterable = {
    [Symbol.iterator](){
      let i = 3;
      return {
        next(){
          return i === 0 ? {value:undefined, done:true} : {value:i--, done:false};
        },
        [Symbol.iterator](){
          return this;
        }
      }
    }
  }
  let iter2 = iterable[Symbol.iterator]();
  for( const a of iter2) log(a); // 3,2,1