Generator function
제너레이터 함수 형태
function* sports(one){
};
const book = function*(one){
};
const music = Object.getPrototypeOf(
function* (){}).constructor;
const gen = new music();
function* 다음에 함수 이름 작성
제너레이터 함수를 호출하면
function* sports(one, two){
yield one + two;
};
log(typeof sports);
const obj = sports(1, 2);
log(typeof obj);
log(obj.next());
// function
// object
// {value: 3, done: false}
Generator 오브젝트는 iterator 오브젝트
함수 코드 실행
const sports = function* (one){
yield one;
};
const obj = sports(100);
log(obj.next());
// {value: 100, done: false}
const fn = new Function("one", "return one");
log(fn(100));
const create = Object.getPrototypeOf(
function*(){}).constructor;
const sports = new create("one", "yield one");
const obj = sports(100);
log(obj.next());
// 100
// {value: 100, done: false}
const gen = function*(){};
/*
1. 오른쪽의 gen을 펼치현 prototype이 있음
- 이것을 펼치면 constructor가 있어야 하는데 없음
- 메소드도 없음
2. __proto__가 있으며 이것을 펼치면 constructor가 있음
- __proto__에 다른 오브젝트의 prototype에 연결된 프로퍼티를 인스턴스 개념으로 생성하여 첨부한 것이 표시됨
3. 즉, GeneratorFunction의 constructor가 첨부된 것
*/
const create = Object.getPrototypeOf(
function*(){}).constructor;
log(create);
const sports = new create("one", "yield one;");
log(typeof sports);
const obj = sports(100);
log(obj.next());
// function GeneratorFunction() { [native code] }
// function
// {value: 100, done: false}
create = (function*(){}).constructor;
constructor가 할당되므로
log(create);
sports = new create(param)
log(typeof sports)
function이라는 것은
const obj = sports(100);
obj.next()
Syntax: [returnValue] = yield [표현식];
function* sports(one){
yield one + 10;
yield;
const value = yield one + 50;
};
const obj = sports(30);
log(obj.next());
log(obj.next());
log(obj.next());
log(obj.next(200));
// {value: 40, done: false}
// {value: undefined, done: false}
// {value: 80, done: false}
// {value: undefined, done: true}
function* sports(one){
yield one;
const check = 20;
};
const obj = sports(10);
log(obj.next());
log(obj.next());
// {value: 10, done: false}
// {value: undefined, done: true}
function* sports(one){
let two = yield one;
let param = yield one + two;
yield param + one;
};
const obj = sports(10);
log(obj.next());
log(obj.next());
log(obj.next(20));
log(obj.next());
// {value: 10, done: false}
// {value: NaN, done: false}
// {value: 30, done: false}
// {value: undefined, done: true}
function* sports(one){}
const obj = sports(10);
첫 번째의 obj.next()를 호출
두 번째의 obj.next()를 호출
세 번째의 obj.next(20)를 호출
네 번째의 obj.next()를 호출
next()는 yield 단위로 실행
next()를 호출하면
function* sports(value){
value += 20;
const param = yield ++value;
value = param + value;
yield ++value;
};
const obj = sports(10);
log(obj.next());
log(obj.next(20));
// {value: 31, done: false}
// {value: 52, done: false}
function* sports(value){
++value;
log(value);
};
const obj = sports(10);
log(obj.next());
// 11
// {value: undefined, done: true}
function* sports(value){
return ++value;
};
const obj = sports(10);
log(obj.next());
log(obj.next());
// {value: 11, done: true}
// {value: undefined, done: true}
함수는 호출될 때마다 변수에 초기값을 설정
제너레이터 함수는
let status = true;
function* sports(){
let count = 0;
while (status){
yield ++count;
};
};
const obj = sports();
log(obj.next());
log(obj.next());
status = false;
log(obj.next());
// {value: 1, done: false}
// {value: 2, done: false}
// {value: undefined, done: true}
yield를 반복하는 형태
let status = true;
첫 번째 next() 호출
while (status){ yield ++count; }
두 번째 next()를 호출
status = false;
세 번째 next() 호출
function* sports(){
return yield yield yield;
};
const obj = sports();
log(obj.next());
log(obj.next(10));
log(obj.next(20));
log(obj.next(30));
// {value: undefined, done: false}
// {value: 10, done: false}
// {value: 20, done: false}
// {value: 30, done: true}
한 줄에 다수의 yield와 return 작성
첫 번째 next() 호출
두 번째 next(10) 호출
세 번째 next(20) 호출
네 번재 next(30) 호출
return 문을 작성하지 않으면
function* sports(){
return [yield yield];
};
const obj = sports();
log(obj.next());
log(obj.next(10));
const last = obj.next(20);
log(last);
log(last.value);
// {value: undefined, done: false}
// {value: 10, done: false}
// {value: [20], done: true}
// [20]
대괄호[] 안에 다수의 yield 작성
next(), next(10) 호출
세 번째 next(20) 호출
console.log()에 {value: Array(1)} 형태로 표시되지만 가독성을 위해 편집함
function* sports(count){
while(true){
yield ++count;
};
};
for (let point of sports(10)){
log(point);
if(point > 12){
break;
};
};
// 11
// 12
// 13
for-of 문으로 제너레이터를 반복 호출
처음 for-of문을 시작하면
다시 sports*() 호출
{done: true}로 종료 처리를 할 수 없으므로
for-of 블록을 실행
이렇게 break;를 만날 때까지
function* sports(count){
while(true){
yield ++count;
};
};
const obj = sports(10);
log(obj.next());
log(obj.return(70));
log(obj.next(50));
// {value: 11, done: false}
// {value: 70, done: true}
// {value: undefined, done: true}
Error를 의도적으로 발생시킴
제너레이터 함수의 catch()문에서 에러를 받음
function* sports(){
try{
yield 10;
} catch (message){
yield message;
};
yield 20;
};
const obj = sports();
log(obj.next());
log(obj.throw("에러 발생"));
log(obj.next());
// {value: 10, done: false}
// {value: 에러 발생, done: false}
// {value: 20, done: false}
function* sports(){
throw "에러 발생";
yield 10;
};
const obj = sports();
try {
const result = obj.next();
} catch (message){
log(message);
};
log(obj.next());
// 에러 발생
// {value: undefined, done: true}
Syntax: yield* 표현식
function* sports(){
yield* [10, 20];
};
const obj = sports();
log(obj.next());
log(obj.next());
// {value: 10, done: false}
// {value: 20, done: false}
function* point(count){
yield count + 5;
yield count + 10;
};
function* sports(value){
yield* point(value);
yield value + 20;
};
const obj = sports(10);
log(obj.next());
log(obj.next());
log(obj.next());
// {value: 15, done: false}
// {value: 20, done: false}
// {value: 30, done: false}
첫 번째의 obj.next()를 호출하면
yield*의 표현식에 함수를 작성했으므로
next()로 호출해야 yield가 수행되지만
다시 point()를 호출한 곳에서 반환 값을 받아 반환
두 번째의 obj.next()를 호출
세 번째의 obj.next() 호출
function* sports(point){
yield point;
yield* sports(point + 10);
};
const obj = sports(10);
log(obj.next());
log(obj.next());
log(obj.next());
// {value: 10, done: false}
// {value: 20, done: false}
// {value: 30, done: false}
첫 번째의 obj.next()를 호출하면
두 번째의 obj.next() 호출
세 번째의 obj.next() 호출
{주의} yield point;가 없으면