이터레이터는 그 자체로 쓸모있기보다, 더 쓸몽 있는 동작이 가능해 진다는 의미가 있다.
이터레이터 프로토콜은 모든 객체를 이터러블 객체로 변환할 수 있다.
class Log {
constructor() {
this.message = []
}
add(message) {
this.message.push({message, timestamp: Date.now()})
}
[Symbol.iterator]() {
return this.messages.values()
}
}
const logList = new Log()
...
for (let log of logList) {
console.log(`${log.message} @ ${ log.timestamp}`)
}
class Log {
//...
[Symbol.iterator]() {
let i = 0
const messages = this.messages
return {
next() {
if(i >= messages.length)
return {value: undefined, done: true}
return { value: messages[i++], done: false}
}
}
}
}
이터레이터를 사용해 자신의 실행을 제어하는 함수를 제네레이터라고 한다. 제네레이터에는 새로운이 개념이 포함된다. 함수의 실행을 개별적 단계로 나눔으로써 함수의 실행을 제어할 수 있고, 실행중인 함수와 통신 할 수 있다.
제네레이터는 두 가지 예외를 제외하고는 일반적인 함수와 같다.
제네레이터는 다음과 같이 작성할 수 있다.
function* rainbow() {
yield 'red';
yield 'orange';
yield 'yellow';
yield 'green'
yield 'blue'
yield 'indigo'
yield 'violet'
}
통신은 yield 표현식을 통해 이뤄진다.
function* interrogate() {
const name = yield "What is your name?"
const color = yield "What is your favorite color?"
return `${name}'s favorite color is ${color}`
}
generator에서 중요한 점은 중요한 값을 return으로 반환하면 안된다. generator가 값을 반환하는 용도로는 yield를 사용해야 하고 return은 generartor를 종료하는 목적으로 사용해야 한다.