이터러블
ES6 에서 도입된 iteration protocol 은 순회 가능한 데이터 컬렉션을 만들기 위해 ECMAScript 사양에 정의하여 미리 약속한 규칙이다.
ES6 이전에는 통일된 규칙 없이 각자 나름의 구조를 가지고 다양한 방법으로 순회할 수 있었다.
ES6 에서는 순회 가능한 데이터 컬렉션을 이터레이션 프로토콜을 준수하는 이터러블 프로토콜로 통일하여 for...of문, 스프레드 문법, 배열 디스트럭처링 할당의 대상으로 사용할 수 있도록 일원화했다.
const array = [1, 2, 3];
console.log(Symbol.iterator in array); // true
for (const item of array){
console.log(item);
}
console.log([...array]); // 스프레드 문법 사용이 가능하다.
const [a, ...b] = array; // 디스트럭처링 할당이 가능하다.
console.log(a, b); // 1, [2, 3]Iteration Protocol
- iterable protocol
Well-known Symbol 인Symbol.iterator를 프로퍼티 키로 사용한 메서드를 직접 구현하거나 프로토타입을 체인을 통해 상속 받은Symbol.iterator메서드를 호출하면 이터레이터 프로토콜을 준수한 이터레이터를 반환한다.
이터러블 프로토콜을 준수한 객체를 이터러블 이라고 한다.
이터러블 확인
// 객체가 null 이 아니고, 프로터티를 가지는데 타입이 함수이다.
const isIterable = v => v !== null && typeof v[Symbol.iterator] === "function";- iterator protocol
next메서드를 소유하며next메서드를 호출하면 이터러블을 순회하며 value 와 done 프로퍼티를 갖는 iterator result object 를 반환한다.
이터레이터 프로토콜을 준수한 객체를 이터레이터라고 한다. 이터레이터는 이터러블의 요소를 탐색하기 위한 포인터 역할을 한다.
const array = [1, 2, 3];
const iterator = array[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 }BuiltIn Iterable
| 빌트인 이터러블 | Symbol.iterator 메서드 |
|---|---|
| Array | Array.prototype[Symbol.iterator] |
| String | String.prototype[Symbol.iterator] |
| Map | Map.prototype[Symbol.iterator] |
| Set | Set.prototype[Symbol.iterator] |
| TypedArray | TypedArray.prototype[Symbol.iterator] |
| arguments | arguments[Symbol.iterator] |
| DOM 컬렉션 | NodeList.prototype[Symbol.iterator] HTMLCollection.prototype[Symbol.iterator] |
사용자 정의 이터러블
이터레이션 프로토콜을 준수하지 않는 일반 객체도 준수하도록 구현하면 이터러블이 된다.
// 아터래이션 프로토콜울 준수하는 객체를 반환하는 함수.
// 지연 평가
// lazy evaluation
const fibonacci = function () {
let [pre, cur] = [0, 1];
return {
[Symbol.iterator]() { return this; }, // iterable protocol
next() { // iterator protocol
[pre, cur] = [cur, pre + cur];
return { value: cur };
}
};
}
// 무한 이터러블
for (const num of fibonacci()) {
if (num > 100) break;
console.log(num);
}
// 배열 디스트럭처링 할당
const [n1, n2, n3] = fibonacci();
console.log(n1, n2, n3);