iterable 이란 "반복 가능하다" 는 뜻으로, for..of 반복문을 적용 가능한 객체입니다.
대표적으로 배열과 문자열이 iterable 합니다.
for..of 반복문 사용 가능배열과 문자열 등 이터러블이 아니어도 for..of 문법을 사용하도록 할 수 있습니다.
배열이 아닌 객체가 for..of 를 사용하기 위해 다음과 같은 동작을 구현하면 됩니다.
for..of 사용시 이터레이터(메서드 next 가 있는 객체) 반환for..of 는 이터레이터를 가지고 동작for..of 의 다음 반복문의 값은 next() 메서드를 호출하여 얻음next() 의 반환 값은 {done: Boolean, value: any} 형태done=true: 반복문 종료done=false: 반복문을 계속 진행, value 에 다음 값 저장이를 위해 Symbol.iterator 를 사용합니다.
객체는 for..of 반복문 시작 시 Symbol.iterator 를 호출합니다.
객체에 Symbol.iterator 라는 메서드를 추가합니다.
이 메서드는 이터레이터를 반환하며 next() 메서드를 정의합니다.
next() 메서드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 :...}형태로 반환
if (this.current <= this.last) {
return { done: false, value: this.current++ };
} else {
return { done: true };
}
}
};
};
for (let num of range) {
alert(num); // 1, then 2, 3, 4, 5
}
Symbol.iterator 가 반환한 객체와 그 객체의 메서드 next() 를 사용하여 반복문을 진행합니다.
for..of 반복문은 결국 이터레이터 객체가 next() 를 이용한다는 것이 핵심입니다.
새로운 객체를 반환하는 게 아니라 기존의 객체에서 next() 를 정의하고 기존 객체 자체를 반환할 수도 있습니다.
let range = {
from: 1,
to: 5,
[Symbol.iterator]() {
this.current = this.from;
return this;
},
next() {
if (this.current <= this.to) {
return { done: false, value: this.current++ };
} else {
return { done: true };
}
}
};
for (let num of range) {
alert(num); // 1, then 2, 3, 4, 5
}
그러나, 새로운 이터러블 객체를 생성했던 위와 달리 range 객체 자체를 이터러블로 사용하고 있으므로, 하나의 객체가 동시에 for..of 반복문을 여러 개 사용할 수 없습니다.
같은 객체이므로 반복 상태를 공유하기 때문입니다.
이터러블과 유사 배열은 서로 구분됩니다.
Symbol.iterator 가 구현된 객체, for..of 사용 가능length 프로퍼티가 있어 배열처럼 보이는 객체유사 배열이라고 해서 이터러블인 것은 아니고, 이터러블이라고 해서 배열인 것도 아닙니다.
그러나 Array.from 메서드를 사용하면 이터러블이나 유사 배열을 배열로 만들어줄 수 있습니다.
Array.from 은 유사 배열이나 이터러블 객체를 받아 새로운 Array 를 반환합니다.
Array.from(arrayLike[, mapFn[, thisArg]])
인덱스와 length 가 있는 유사 배열과 Symbol.iterator 를 구현한 객체의 경우를 배열화합니다.