📝 서론
이터레이터 이터러블 이터러블 프로토콜에 대해 js 개발자라면 굉장히 많이 들어보셨을 것 같습니다.
다양한 반복스러운 일(?) 들에 대해 조금 더 스마트하게 작성할 수 있는 방법들을 고민하다가 이터러블 프로토콜을 적용시켜 코드를 작성해야겠다! 라고 생각하며, 조금 살펴본 간단한 개념들에 대해 정리하겠습니다.
TIL 정도의 분량입니다.
💁🏼♀️ 이터러블? 이터레이터? 이터러블 프로토콜? 그게 뭔데?
알고보면 간단한(사실 안간단) 개념인데 처음 접했을때는 왜이리 어렵고 복잡하게 느껴졌는지 모르겠습니다.
이터러블?
이터러블은?
이터레이터를 리턴하는 Symbol.iterator를 가진 값 입니다.
const iterable = {
[Symbol.iterator]() {
}
}
이터레이터?
{value, done} 객체를 리턴하는 next() 를 가진 값 입니다.
const iterable = {
[Symbol.iterator]() {
let i = 3;
return {
next() {
return i === 0 ? { done: true } : { value: i--, done: false }
}
}
}
}
위 코드를 보면 이터러블은 이터레이터를 리턴하는 [Symbol.iterator]를 가지고 있으며,
이터레이터는 {value, done} 객체를 리턴하는 next() 를 가지고 있습니다.
이터러블 프로토콜?
이터러블/이터레이터 프로토콜은 이터러블을 for...of, 전개연산자 등과 함께 동작하도록한 규약 입니다.
따라서 아래 코드는 이터러블 프로토콜을 따르고 있기 때문에 for..of로 순회가 가능합니다.
const iterable = {
[Symbol.iterator]() {
let i = 3;
return {
next() {
return i === 0 ? { done: true } : { value: i--, done: false }
}
}
}
}
for(a of iterable) {
console.log(a);
}
// 3
// 2
// 1
for of 는 시작하자마다 [Symbol.iterator]를 실행하여 이터레이터를 리턴합니다.
그리고 돌면서 done이 false 가 될때까지 순회 합니다.
따라서 위와 같이 순회가 가능한 것 입니다.
실제로 여러분이 알고계신 array, string, nodeList 등이 이터러블 프로토콜을 따르고 있습니다.
const arr = [3, 2, 1];
for(a of arr) {
console.log(a);
}
// 3
// 2
// 1
이터러블 프로토콜을 따르고 있는 객체라면 어떤 객체든 for of 적용이 가능합니다.
well-formed iterable
우리가 구현한 이터러블은 array, string, nodeList 등에서 구현된 이터러블이랑은 조금 다릅니다.
array, string, nodeList등은 well-formed iterable 입니다.
어떤 말이냐면 이터러블을 통해 이터레이터가 리턴된, 그 이터레이터는 이터레이터 이자,
또 자신을 리턴하는 [Symbol.iterator]를 가진 이터러블이라는 것입니다.
이를 well-formed iterable 이라 부릅니다.
코드로 표현하면 아래와 같습니다.
const iterable = {
[Symbol.iterator]() {
let i = 3;
return {
next() {
return i === 0 ? { done: true } : { value: i--, done: false }
},
[Symbol.iterator]() {
return this;
}
}
}
}
이렇게 만든 이터러블은 아래와 같이 사용할 수 있습니다.
const iter2 = iterable[Symbol.iterator]();
for (it of iter2) {
console.log(it);
}
// 3
// 2
// 1
제가 이터레이터를 만들고 for of 를 넣는데 사실 위와 같은 경우는 아래와 같이 써도 되긴 합니다.
for (it of iterable) {
console.log(it);
}
// 3
// 2
// 1
근데 well-formed 한 이터러블을 만들면 이터러블이 진행된 시점을 기억하고,
그 시점부터 다시 시작 할 수 있습니다.
예를 들어, 아래와 같습니다.
const iter2 = iterable[Symbol.iterator]();
iter.next(); // ---> 여기서 3 실행됨
for (it of iter2) {
console.log(it);
}
// 2
// 1
iter2 는 자신을 리턴하는 Symbol.iterator를 가진 이터러블 이기때문에 for of 로 순회할 수 있습니다.
array가 well-formed iterable 이라는 증거는 아래와 같이 증명할 수 있습니다.
const arrayIterable = [3, 2, 1][Symbol.iterator]();
arrayIterable[Symbol.iterator]() == arrayIterable; // true
전개연산자
전개 연산자 또한 이터러블/ 이터레이블 프로토콜을 따르고 있습니다.
따라서 아래와 같이 전개연산자를 사용할 수 있습니다.
const arr = [1, 2, 3]
const arr2 = [4, 5, 6]
console.log([...arr, ...arr2]);
// [1, 2, 3, 4, 5, 6]
'javascript > 함수형프로그래밍과 ES6' 카테고리의 다른 글
range와 느긋한 L.range (0) | 2021.10.26 |
---|