function makeInfiniteEnergyGenerator() {
let energy = 0;
return function (booster = 0) {
if(booster) {
energy += booster;
}else {
energy++
}
return energy;
};
};
const energy = makeInfiniteEnergyGenerator();
for (let i = 0; i < 5; i++) {
console.log(energy());
}
console.log(energy(5));
- 제네레이터 함수는 첫번째 호출을 하면 일반 함수와 달리 자신을 실행시키지 않는다. 정확히는 실행시키는데 필요한 도구를 갖고있는 객체를 만들어서 넘겨준다.
- 만들어진 객체(energyGenrator)는 next() 메서드를 가지고 있는데,
제네레이터 함수 본체를 실행을 재개시킬 수 있는 함수이다.
- for문에서 energyGenrator.next() 로 infiniteEnergyGenrator()를 실행한다.
- 그리고 실행된 함수로가서 energy = 1을 주고 const booster = yield energy;로 넘어간다.
- yield는 제네레이터를 멈추는 키워드이다. 멈춘 상태에서 yield뒤에 있는 값을 호출자 에게 돌려준다. 호출자는 next()이다.
즉, next( )의 반환값으로 energy 값을 주는 돌려주는 것이다.
- 이때 값을 단순하게 1 그대로 돌려주는게 아니라, 객체로 한번 포장해서 돌려준다. (value에 돌려받은 값을 넣어주고 done이라는 속성과함께)

- 값을 호출자에게 돌려주고 난뒤, for문의 0은 끝났고
이제 i=1일때 next()로 함수가 재개 되면서 yield로 멈췄던 energy의 값이 booster로 대입된다. 그리고 아래 if문이 실행되면서 energy가 2가된다.
- while문이 true로 무한 루프이기 때문이 energy가 2가된 상태에서 yield를 만나 2가된 energy값을 next()에게 돌려준다.
- 이렇게 반복해서 5까지 나온다.
- next( )에 인자값이 들어가면 yield가 booster에게 리턴한 것 처럼 인자값이 들어간다. 즉, booster가 5가 된다.
그리고 아래 if문이 실행되면서 energy는 10이되고 yield를 만나 멈추고 10을 출력한다.
- 실제로는 무한 루프이지만 next( )가 호출되기 전까지는 멈춰있는다.
다시 재개 될 때 기존의 함수상태를 그대로 유지하고 있기 떄문에 energy값을 클로저 공간에 가둬둘 테크닉을 쓸 필요가없다. 함수가 종료가안되니까.
- done속성은 제너레이터가 return값을 가지면 함수를 종료하고 true로 만든다.
이것을 이용해 마지막에 반환된 값의 done이 true인지 false인지 확인하고, next()로 다시 재개시킬지 말지 판단할때 사용한다.
function* infiniteEnergyGenrator() {
let energy = 1;
while (true) {
const booster = yield energy; // yield 뒤에 energy 값을 for문 next()의 값으로 돌려준다.
if (booster){
energy += booster;
}else{
energy++;
}
}
}
const energyGenrator = infiniteEnergyGenrator(); // 실행되지 않고 실행시키는데 필요한 도구를 갖고있는 객체를 만든 것
for(let i = 0; i <5; i++){
console.log(energyGenrator.next());
}
// i가 0일때 next()라는 메서드를 만나서 infiniteEnergyGenrator() 함수를 실행한다.
console.log(energyGenrator.next(5));