iterator의 구현을 돕는 Generator
const N2 = class {
constructor (max) {
this.max = max;
}
[Symbol.iterator](){
let cursor = 0, max = this.max;
return {
done: flase,
next() {
if (cursor > max) {
this.done = true;
} else {
this.value = cursor * cursor;
cursor++;
}
return this;
}
}
}
}
const generator = function* (max) {
let cursor = 0;
while(cursor < max) {
yield cursor * cursor;
cursor++;
}
}
Generator 를 복잡하게 짰을 때 iterator 로 번역은 할 수 있지만.. 번역할 엄두가 안나게 된다.
iterator 로 작성하려면 훨씬 복잡해지기 때문이다.
하지만 이를 도와주는 것이 있다.
babel
Generator 를 짜서 babel을 돌려보면 가공할만한 일이 일어난다.
done과 value는 yield가 한번에 처리한다.
yield
가 value를 리턴함으로써 yield하는 동안엔 done이 다 false이다.
더 이상 yield
하지 않고 generator를 빠져나올 때 done이 true가 된다.
const generator = function* (max) {
let cursor = 0;
while(cursor < max) {
yield cursor * cursor;
cursor++;
}
}
console.log([...generator(5)]); // [0, 1, 4, 9, 16]
console.log(...generator(5)); // 0, 1, 4, 9, 16
for (const v of generator(5)) console.log(v);
// 0
// 1
// 4
// 9
//16
Generator 를 호출하면 iterator 이자 iterable 객체를 return 한다.
그래서 iterable 과 똑같은 결과가 나오게 된다.
Generator 는 계속 호출해도 똑같이 반복한다.
iterable 이자 iterator 객체이기 때문이다. iterator 객체이기만하면 한번 돌고 끝일 것이다.
iterable이자 iterator 객체이기 때문에 계속 반복할 수 있는 것이다.
배열도 마찬가지로 iterable이자 iterator 객체이기 때문에 반복을 계속해도 계속 반복할 수 있는 것이다.
정리
- iterator - 상태에 대한 관리요소 : 스코프를 활용해서 자율변수 사용 or 인스턴스를 만들어 필드에서 next가 관리
- generator - 상태에 대한 관리 : 상태를 인자, 지역변수 갱신으로 관리한다. 훨씬 간편하게, 그리고 이해하기 쉽게 관리할 수 있다. 그리고 반복시키는 것도 제어문으로 돌리면되고 yield만 해주면 된다. 코드를 작성하는 부담이 확 줄어든다.