iterable은 말 그대로 반복 가능한 객체를 의미합니다. 대표적으로 배열, 문자열 등등이 있습니다. 이러한 개념을 활용하면 어떤 객체든 iterable하게 만들 수 있습니다.
iterable한 객체를 만들기 위해서는 Symbol.iterator
메서드를 활용합니다. 객체는 이를 가지고 있어야하죠. 아래에 코드를 확인하세요.
const range = {
from: 1,
to: 5
}
// for ... of가 시작되면 Symbol.iterator를 호출합니다.
range[Symbol.iterator] = function() {
// Symbol.iterator는 iterator 객체를 반환하고요. for ... of는 이 iterator객체만을 대상으로 동작합니다.
return {
current: this.from,
last: this.to,
// for ... of의 반복마다 next가 호출됩니다.
next() {
if (this.current <= this.last) {
return {done: false, value: this.current++}
} else {
return {done: true}
}
}
}
}
for (num of range) {
console.log(num); // 1, 2, 3, 4, 5
}
for ... of
문법은 Symbol.iterator
메서드가 반환한 iterator
를 대상으로 순회합니다. 각 반복마다 next
메서드를 호출하구요. 만약 Symbol.iterator
가 없으면 iterable 객체가 아니기 때문에 반복문을 사용할때 에러가 납니다. 주의하세요!!
자기 자신을 iterator
로 만들어주면 코드가 한결 더 편안해집니다. 아래 코드를 확인하세요.
const range = {
from: 1,
to: 5,
[Symbol.iterator]() {
this.current = this.from;
// 이렇게 iterator를 자기 자신으로 설정하면 코드가 훨씬 간결해집니다.
return this; // for ... of가 range.[Symbol.iterator]를 호출하면 this = range가 되겠죠.
},
next() {
if (this.current <= this.to) {
return { done: false, value: this.current++}
} else {
return { done: true }
}
}
}
for (num of range) {
console.log(num);
}
자 그럼 이를 활용해서 우리는 반복되는 iterable한 객체를 조금 더 분해할 수 있습니다. 아래 코드처럼요.
const str = 'seo';
// iterator객체를 할당해서 조금 더 명시적으로 반복문을 제어할 수도 있습니다.
const iterator = str[Symbol.iterator]();
while(true) {
let result = iterator.next();
if (result.done) break;
console.log(result.value);
}
헷갈리지 마세요. 유사배열은 length
index
프로퍼티를 가진 객체를 의미합니다. Symbol.iterator
를 가지고 있지 않기 때문에 반복문을 사용할 수 없습니다.
또한 iterable과 유사배열 둘 다 엄밀히 따지면 배열은 아니기 때문에 배열 메서드를 사용할 수 없어요. 만약 배열 메서드를 사용하고 싶으면 Array.from
을 사용해 배열로 변환해주세요.
/**
* index와 length 프로퍼티가 있으면 이를 '유사배열' 이라고 합니다.
* 유사배열과 iterable은 엄연히 다릅니다. 유사배열엔 [Symbol.iterator] 메소드가 정의되어있지 않죠?
* 그리고 둘 다 배열은 아니기 때문에 배열 메소드를 활용할 수 없습니다.
* */
const arrayLike = {
0: 'hello',
1: 'world',
length: 2
}
for (let item of arrayLike) {
console.log(item); // TypeError: arrayLike is not iterable
}
// 유사배열과 iterable을 배열로 활용하기 위해서는 Array.from을 사용하면 됩니다.
const array = Array.from(arrayLike);
console.log(array); // [ 'hello', 'world' ]
오늘 iterable에 대해서 알아봤는데요. Symbol.iterator
가 있어야 iterable객체인 것을 알았죠. 되게 간단하지만 이제 javascript 공부를 시작하신 분들은 몰랐을 거라 생각해요. 이 글이 도움이 되셨으면 좋겠습니다.