이번 시간에는 순회와 이터러블에 대해서 공부해보겠습니다. 📕
➡️ 함수형 프로그래밍에서 리스트 순회는 매우 중요합니다.
const list = [1, 2, 3, 4, 5];
for (let i =0; i<list.length; i++){
log(list[i]);
}
const str = "abcd"
for (let i =0; i<str.length; i++){
log(str[i]);
}
✅ 훨씬 간결하게 리스트를 순회할 수 있습니다.
const list = [1, 2, 3, 4, 5];
for (const val of list) {
log(val);
}
➡️ Array, Set, Map의 순회에 대한 예시를 살펴보겠습니다.
const arr = [1, 2, 3];
let iter1 = arr[Symbol.iterator](); // 이터레이터 생성
for (const a of iter1) log(a);
// result : 1 2 3
const set = new Set([1, 2, 3]);
for (const a of set) log(a);
// result : 1 2 3
const map = new Map([['a', 1], ['b', 2], ['c', 3]]);
for (const a of map) log(a); // result : ["a", 1], ["b", 2], ["c", 3]
for (const a of map.keys()) log(a); // 키 값만 출력됩니다.
for (const a of map.values()) log(a);
for (const a of map.entries()) log(a);
map.keys()
는 이터레이터를 리턴합니다. 이 이터레이터는 value에 key만 담게 됩니다. map.values()
는 이터레이터 value에 map의 value 값만 담깁니다.
map.entries()
는 map에서 key, value 값을 모두 반환합니다.
아래 그림에서 확인할 수 있듯이 Array인 arr
은 Symbol.iterator
메소드를 가지고 있습니다.
[Symbol.iterator] ()
를 가진 값[예시]
➡️ value에 들어오는 값을 for (const a of arr) log(a);
에서 a
에 넣어주게 되고, done
이 true
가 되면 반복문을 빠져나오게 됩니다.
➡️ 사용자가 원하는대로 이터러블을 정의하고 사용할 수 있습니다.
const iterable = {
[Symbol.iterator]() {
let i = 3;
return {
next() {
return i == 0 ? {done: true} : {value: i--, done: false};
},
[Symbol.iterator]() {
return this; // 자기 자신을 리턴하게 한다. (well-formed iterator)
}
}
}
};
let iterator = iterable[Symbol.iterator]();
log(iterator.next()); // 3
log(iterator.next()); // 2
log(iterator.next()); // 1
for (const a of iterator) log(a); // 순회도 가능하다.
const arr2 = [1, 2, 3];
let iter2 = arr2[Symbol.iterator]();
iter2.next();
log(iter2[Symbol.iterator]() == iter2); // true
for (const a of iter2) log(a);
➡️ 일부분이 순회된 후에 다시 순회해도 이어서 할 수 있게 하는 iterator를 well-formed iterator라고 합니다.
➡️ 전재 연산자도 마찬가지로 이터러블/이터레이터 프로토콜을 따릅니다.
const a = [1, 2];
a[Symbol.iterator] = null; // 오류 발생
console.log([...a]); // [1, 2]
이번 시간에는 이터러블과 이터레이터에 대해서 공부를 해보았습니다.
ES6에서 이터러블과 이터레이터의 개념은 아주 중요하니 꼭 숙지하시면 좋겠습니다.
다음 시간에는 제너레이터와 이터레이터에 대해 다뤄보겠습니다!