프로그래밍 공부/Frontend

Iterable 이터러블

Kevinkb 2021. 9. 26. 11:07

자바스크립트에는 for.. of반복문 등을 이용해 반복 동작 수행이 가능하다. 이렇게 반복 동작이 가능한 것을 '이터러블(iterable, 반복 가능한)'이라고 한다. 자바스크립트에서 어떤 타입은 반복 동작 수행이 가능하지 않은 반면에(ex. object 등), 어떤 타입은 가능하다. 대표적으로 문자열과 배열이 이터러블의 예이다. 하지만 itertation protocol을 이용해 객체를 이터러블하게 만들 수 있다.

Iteration protocol

ES6 문법, 객체에 반복 동작을 수행할 수 있도록 만들어주는 protocol이다. 일정 규칙만 충족된다면 어떠한 객체에 의해서도 구현될 수 있다. 2개의 protocol이 있다. iterable protocoliterator protocol

Iterable protocol

iterable protocol은 객체들이 반복 동작을 정의하는 것을 허용한다. 이터러블 하기 위해서는 @@iterator 메소드를 구현해야 하는데, 이것은 객체가 Symbol.iterator 키 속성을 가져야 한다는 것을 의미한다. 즉, 모든 자바스크립트 객체는 반복 동작을 수행하려면 Symbol.iterator 키 속성을 가져야만 한다는 것이다.

콘솔 창에서는 Symbol(Symbol.iterator)로 확인할 수 있다.

어떠한 객체가 반복되어야 한다면 이 객체의 @@iterator 메소드가 인수 없이 호출되고, 반환된 iterator는 반복을 통해서 획득할 값들을 얻을 때 사용된다.

※내장 iterables
String, Array, TypedArray, Map and Set 는 모두 내장 iterable이다. 이 객체들의 프로토타입 객체들은 이미 모두 @@iterator 메소드를 가지고 있기 때문이다.

Iterator protocol

iterator protocol은 value들의 sequence(연속적인 순서)를 만드는 표준 방법을 정의한다. 객체가 next() 메소드를 가지고 있고 아래에 규칙을 만족한다면 그 객체는 iterator이다. 즉, obj[Symbol.iterator]의 결과를 이터레이터라고 부르고 이터레이터는 이어지는 반복 과정을 처리한다.

next() 메서드 : 아래의 2가지 속성을 가지며 argument가 없고 object를 반환하는 함수

  • done (boolean)
    iteratoer(반복자)가 마지막 반복 작업을 마칠 경우 true. 만약 iterator에 return 값이 있다면 value의 값으로 지정된다.
    iterator의 작업이 남아있을 경우 false.

  • value
    iterator로 부터 반환되는 모든 자바스크립트 값이며 done이 true일 경우 생략될 수 있다.

사용 예시

let range = {
  from: 1,
  to: 5
};

// 1. for..of 최초 호출 시, Symbol.iterator가 호출
range[Symbol.iterator] = function() {

  // Symbol.iterator는 이터레이터 객체를 반환
  // 2. 이후 for..of는 반환된 이터레이터 객체만을 대상으로 동작하는데, 이때 다음 값도 정해집니다.
  return {
    current: this.from,
    last: this.to,

    // 3. for..of 반복문에 의해 반복마다 next()가 호출된다.
    next() {
      // 4. next()는 속성 done, value를 가지며 객체 {done:.., value :...}형태로 반환해야 한다.
      if (this.current <= this.last) {
        return { done: false, value: this.current++ };
      } else {
      // done이 true일 경우 생략될 수 있다.
        return { done: true };
      }
    }
  };
};

// 반복 동작한다
for (let num of range) {
  alert(num); // 1, then 2, 3, 4, 5
}