본문 바로가기
언어/자바스크립트

Iteration Protocol(for of, spread)

by SeungYn 2023. 3. 21.

자바스크립트를 사용하다 보면 자연스럽게 [... arr]처럼 스프레드 연산자를 사용한다.

그게 왜 가능 할까? 한번 알아보자.

 

이터레이션 프로토콜(Iteration Protocol)

이터레이션 프로토콜이란?

반복, 순회를 하기 위해서 따르는 규격, 약속, 인터페이스이다.

이 프로토콜을 따르면 for of나 spread 연산자를 사용 가능 하다.

 

자바스크립트에서는 Array, String, Map, Set이 녀석들이 이 프로토콜을 따른다.

 

그럼 이 이터레이션을 따르는 것은 뭘까?

그건 Iterable, Iterator 프로토콜을 따르면 된다. 간단하다.

아래 두 가지만 기억하면 된다.

더보기

Iterable: Iterator을 리턴하는 [Sysmbol.iterator]()을 가진 값

Iterator: next() 함수를 가진 객체를 리턴하는데 next라는 함수에는 {value, done}를 리턴하면 된다.

 

그러면 Array에 [Sysmbol.iterator]()이 있는지 확인해 보자

 

확인을 해보면 정말 들어있다. 그러면 Iterator(next() 함수를 가진 객체를 리턴하는 객체)도 있는지 확인해 보면

next 프로퍼티가 있는지 확인하면 true가 출력되고

next()를 호출하면 첫 번째 값인 3이 나오는 걸 볼 수 있음

 

이제 직접 [3,2,1]을 만들어보자

다시 이터레이션 프로토콜을 살펴보면 반복, 순회를 위한 규약, 인터페이스이다. 그럼 이 인터페이스를 따르려면

iterable와 iterator 프로토콜을 따라야 한다.

iterable은 Iterator을 리턴하는 Sysmbol.iterator을 가진 값이고 iterator은 next() 함수를 가진 객체를 리턴하는데 next라는 함수에는 {value, done}를 리턴하면 된다.이다.

아래 코드를 보면 testIterable라는 객체는 Symbol.iterator라는 함수를 가지는 데 이 함수는 next()라는 함수를 포함한 객체를 리턴하고 있어서 이터레이션 프로토콜을 따르고 있다.

 

const testIterable = {
  [Symbol.iterator]() {
    let i = 3;
    return {
      next() {
        return i === 0 ? { done: true } : { value: i--, done: false };
      },
    };
  },
};

 

위에 작성한 코드 결과도 for of와 스프레드 연산자가 잘 작동되고 있다.

 

그러면 이제 저 next()라는 애는 뭘까?

next는 그냥 호출하면 현재 값과 더 이상 순회할 게 있는지 없는지를 알려주는 애이다.

 

여기서 잘 만들어진 이터레이터는 next를 호출하다 for of나 스프레드 연산자를 사용하면 next 다음 값들부터 순회를 하도록 되어있다. 이것을 구현하려면

아래처럼 [Symbol.iterator]의 리턴 값을 this로 해주면 된다. 그러면

 

const testIterable = {
  [Symbol.iterator]() {
    let i = 3;
    return {
      next() {
        return i === 0 ? { done: true } : { value: i--, done: false };
      },
      [Symbol.iterator]() {
        return this;
      },
    };
  },
};

 

next로 3이 출력되고 나머지 2, 1이 스프레드 연산자로 출력되는 것을 확인할 수 있다.

지금까지 당연하게 쓴 for of, spread가 어떻게 돌아가는지 확인했다. 쉽지 않다.