이미 자바스크립트에는 for 루프 부터 map, forEach 와 같은 반복문을 만들어주는 컬렉션이 있다. 그렇다면 iterator와 iterable 은뭘까 ?
{value, done}
{value : undefined ,done: true}
객체를 반환 받는다.예시 1 ) 문자열에 iterator 프로퍼티를 추가하여 iterator 실행해보기
let iterator = '예시'[Symbol.iterator]()
iterator.next() // { value:'예', done: false}
iterator.next() // { value:'시', done: false}
iterator.next() // { value:undefined , done: true}
예시 2) iterator 객체는 아래와 같이 직접 구현 될 수도 있다.
let counter = 0
let limit = 3
const iteratorObjectProtocol = {
next: function() {
counter++
if (counter >= limit) return { value: undefined, done: true }
return { value: counter, done: false }
},
}
console.log(iteratorObjectProtocol.next())
// { value: 1, done: false}
console.log(iteratorObjectProtocol.next())
// { value: 2, done: false}
console.log(iteratorObjectProtocol.next())
// { value: undefined, done: true}
Array
와 Map
과 같은 타입은 iterable 이 구현되어 있는 built-in iterables
이다.for...of
를 통해 iterator 값들을 순환 할 수 있고, 위에서 보았듯이 펼침 연산자 (spread operator)
로 표현 시, 배열형태로 반환 접근 할 수 있다.@@iterator
메소드를 구현해야 한다.object[Symbol.iterator] : iterator 메서드 정의
Built in iterables 종류
Array , TypedArray, String, Map, Set
예시 1) 위에서 구현한 iteratorObjectProtocol
메서드를 [Symbol.iterator]
에 정의해보도록 하겠다.
let counter = 0
let limit = 3
const iteratorObjectProtocol = {
next: function() {
counter++
if (counter >= limit) return { value: undefined, done: true }
return { value: counter, done: false }
},
}
const obj = {
[Symbol.iterator]: function() {
return iteratorObjectProtocol
},
}
console.log([...obj])
// [1,2]
Symbole.iterator
프로퍼티에 정의한 iteratorObjectProtocol
이 실행된 결과물이 배열의 형태로 담겨져 있는 것을 알 수 있다.예시 2 ) Generator 함수를 통해서 간결화하기
const obj = {
[Symbol.iterator]: function*() {
yield 1
yield 2
},
}
for (let value of obj) {
console.log(value)
}
// 1, 2
위의 예시에서 사용한 Generator 에 대해서 더 자세히 알아보도록 하겠다.
Iterable
을 생성하는 함수로, 위에서 우리가 직접 제어문으로 구현한 Iterator 함수를 간결화 시킨 것이라고 보면 된다.제너레이터를 반환
한다.iterable
이면서 동시에 iterator
인 객체이다.예시 1) 제너레이터 함수로부터 반환되는 제너레이터
function* genFunc() {
for (let value of [1, 2]) yield value
}
const generatorObj1 = genFunc()
// Iterable 이므로 for..of를 통해서 값 반환
for (let value of generatorObj) {
console.log(value) // 1 , 2
}
// next 메서드를 가지고 있는 iterator
const generatorObj2 = getFunc()
console.log(generatorObj2.next())
// {value:1, done:false}
console.log(generatorObj2.next())
// {value:2, done:false}
console.log(generatorObj2.next())
// {value:undefined, done:true}
이렇게 JavaScript의 ES6의 iterable protocol과 Generator를 알아보았다.
사실 iterable protocol은 자주 사용할 일은 없지만, 리덕스 사가를 사용한다면 Generator 함수 사용이 불가피하다.
이전에는 단순히 Generator 함수를 함수의 순서를 제어해주는 함수라고만 생각했는데, iterable protocol과 함께 보면 Generator 함수가 어떻게 동작하고,
반환되는 Generator의 속성에 대해 더 깊이 알 수 있다