모던 자바스크립트 입문(아소 히로시, 길벗, 2018)에서 발췌하여 정리한 내용입니다.
제너레이터는 다음과 같은 성질을 지닌 함수입니다.
이터레이터 리절트(iterator result)
는 value 프로퍼티와 done 프로퍼티를 가진 객체입니다.
제너레이터는 function*
문으로 정의한 함수이며, 하나 이상의 yield
표현식을 포함합니다.
function* gen() {
yield 1; // point 1
yield 2; // point 2
yield 3; // point 3
}
let iter = gen(); // 이터레이터를 변수 iter에 대입
console.log(iter.next()); // -> Object {value: 1, done: false}
console.log(iter.next()); // -> Object {value: 2, done: false}
console.log(iter.next()); // -> Object {value: 3, done: false}
console.log(iter.next()); // -> Object {value: undefined, done: true}
yield* iterable
문을 사용하면 위의 코드를 더 짧게 쓸 수 있습니다.
function* gen() {
yield* [1, 2, 3] // yield* 뒤에는 iterable한 객체만 와야 합니다.(String, Array 등)
}
...
제너레이터 함수인 gen은 호출해도 바로 실행되지 않습니다. 그 대신 이터레이터를 반환합니다.
이터레이터의 next 메서드가 호출되면 함수의 첫 번째 yield 연산자의 위치까지 실행하며 결괏값으로 이터레이터 리절트(result)를 반환합니다. 이 때 제너레이터 함수의 내부 처리는 포인트 1에서 일시 정지 상태가 됩니다.
next 메서드가 한 번 더 호출되면 함수의 두 번째 yield 연산자의 위치까지 실행하며 iterator result를 반환하고 포인트 2에서 일시 정지 상태가 됩니다.
즉, 제너레이터 함수의 yield
는 프로그램이 일시적으로 정지하는 위치입니다.
그리고 제너레이터로 생성한 이터레이터의 next
메서드는 제너레이터 함수의 상태를 일시 정지 상태에서 실행 상태로 바꾸는 역할을 합니다.
yield
에 지정한 값을 next
메서드의 반환값(iterator result의 value)이 되어 바깥으로 산출됩니다. yield문의 사용법은 return
문의 사용법과 같습니다.
yield;
yield 표현식;
제너레이터로 생성한 이터레이터는 반복할 수 있기 때문에(iterable하기 때문에) for/of
문으로 반복해서 처리(iteration)할 수 있습니다.
function* gen() {
yield 1; // point 1
yield 2; // point 2
yield 3; // point 3
}
let iter = gen(); // 이터레이터를 변수 iter에 대입
for (let v of iter) console.log(v); // 1, 2, 3을 순서대로 표시한다.
제너레이터는 이터레이터를 생성하여 각 단계의 반복을 제어할 수 있기 때문에 while (true) { ... }
같은 황당한 문법을 활용할 수 있게 해줍니다.
function* generator() {
let i = 0;
while (true) {
yield i++;
}
}
const gen = generator(); // 이터레이터 생성
gen.next(); // Object {value: 0, done: false}
gen.next(); // Object {value: 1, done: false}
gen.next(); // Object {value: 2, done: false}
.
.
.