generator function을 통해 반환된 객체이다. Iterable protocol을 만족하면서 Iterator protocol을 만족하는 객체이다.
const generator = function*() {
yield 1;
}
console.dir(generator()); // generator
generator의 특징을알기 위해서는 Iterable protocol과 Iterator protocol에 대해 알아야 한다.
Iterable protocol은 Symbol.iterator
를 키로 갖는 인자가 없고 iterator
객체를 반환하는 함수여야 한다.
아래의 사항들을 만족한다면 Iterator 객체이다.
next()
메소드를 갖는다.next()
메소드는 {value: any, done: boolean}
형식의 IteratorResult
객체를 반환한다.Iterable protocol
과 iterator protocol
을 만족하는 객체를 만든다면 for...of
나 spread 연산자와 같은 기능을 사용할 수 있다.
const object = {
[Symbol.iterator]() {
return {
v: [1,2,3],
next() {
return {
done: this.v.length === 0,
value: this.v.shift(),
}
}
}
}
}
for (const iterator of object) {
console.log(iterator)
} // 1,2,3
console.log(...object); // 1 2 3
console.log(new Array(...object)) // [1,2,3]
Generator.prototype.next()
: generator를 재개하는 메소드이다. next()함수의 인자로 제너레이터 내부에 yield
에게 값을 전달할 수 있다.const gen = function*() {
let i = 0;
while(true){
let v;
v = yield i++;
console.log(v)
}
}();
console.log(gen.next(4)); // {value: 0, done: false}
console.log(gen.next(5));
// 4,
// {value: 1, done: false}
Generator.prototype.return()
: yield
부분에 return
문이 들어간 것 처럼 작동한다. try...catch
문과 함께라면 제너레이터에게 제너레이터가 종료되었음을 알릴 수 있다.const gen = function*(){
yield 1;
try {
yield 2;
yield 3;
} finally {
yield 'clean up';
}
}
const gen1 = gen();
console.log(gen1.next()); // {value: 1, done: false}
console.log(gen1.return('early return')); // {value: 'early return', done: true');
console.log(gen1.next()); // {value: undefined, done: false}
const gen2 = gen();
console.log(gen2.next()); // {value: 1, done: false}
console.log(gen2.next()); // {value: 2, done: false}
console.log(gen2.return('early return')); // {value: 'clean up', done:false}
console.log(gen2.next()); // {value: 'early return', done:true}
console.log(gen2.next()); // {value: 'undefined', done:true}
try...catch
블록에서 return()
이 실행된다면 finally 문의 yield
가 실행되고 done
이 true가 된다.
Generator.prototype.throw()
: yield된 부분에서 throw
한 것처럼 작동하게 된다. try...catch
문과 같이 사용한다면 catch
문으로 바로 이동할 수 있다.function* gen4() {
while (true) {
try {
yield 42;
} catch (e) {
console.log('Error caught!');
}
}
}
const g = gen4();
g.next();
// { value: 42, done: false }
g.throw(new Error('Something went wrong'));
// "Error caught!"
// { value: 42, done: false }