이터러블 객체는 배열을 일반화한 객체이다. 이터러블이라는 개념을 사용하면 어떤 객체에든 for … of 반복문을 적용할 수 있다.

배열과 문자열, Set, Map, Arguments… 등은 대표적인 이터러블의 예다. 배열이 아닌 객체가 있는데, 이 객체가 어떤 것들의 컬렉션(목록, 집합)을 나타내고 있는 경우, for … of 문법을 적용할 수 있다면 컬렉션을 순회하는 데 유용할 것이다.

이터러블 프로토콜은 반복, 순회 기능을 사용하는 주체 간의 통일된 규격을 의미한다. 이터러블 프로토콜을 준수하는 객체들은 키 Symbol.iterator(well-known 심볼)의 값으로 이터레이터를 반환하는 메서드를 가진다. 공통 기능으로 for … of, 스프레드 문법, 배열 디스트럭쳐링을 사용할 수 있다.

Symbol.iterator

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

// for (let num of range) ... num=1,2,3,4,5?

예시의 객체 range를 이터러블로 만들려면 (for…of가 동작하게 하려면) 객체에 Symbol.iterator(특수 내장 심볼)이라는 메서드를 추가하여 아래와 같은 일이 벌어지도록 해야 한다.

  1. for … of 가 시작되자마자 for…of는 Symbol.iterator를 호출한다. (없으면 에러 발생.) Symbol.iterator는 반드시 이터레이터(메서드 next가 있는 객체)를 반환해야 한다.
  2. 이후 for…of는 반환된 객체(이터레이터)만을 대상으로 동작한다.
  3. for…of에 다음 값이 필요하면, for…of는 이터레이터의 next() 메서드를 호출한다.
  4. next()의 반환 값은 {done: Boolean, value: any}와 같은 형태여야 한다. done=true는 반복이 종료되었음을 의미한다. done=false일 땐 value에 다음 값이 저장된다.

range를 이터러블로 만들어 주는 코드는 아래와 같다.

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

range[Symbol.iterator] = function () {
	return { // 이터레이터를 반환한다.
		current: this.from,
		last: this.to,

		next() {
				if( this.current <= this.last ) {
					return { done:false, value: this.current++ };
				} else {
					return { done:true };
				}
			}
	};
};

for (let num of range) {
	alert(num); // 1, 2, 3, 4, 5
}

이터러블 객체의 핵심은 관심사의 분리에 있다.

이렇게 하면 이터레이터와 반복 대상인 객체를 분리할 수 있다.