: 함수의 실행을 중간에 멈췄다가 재개할 수 있는 기능
*
을 붙여서 생성yield
키워드 사용.next()
메소드를 사용하여 가장 가까운 yield문을 만날때까지 코드 실행function* fn(){
yield 1;
yield 2;
yield 3;
return 'finish';
}
const a = fn();
a; // fn {<suspended>}
// generator 객체 반환되고, 내부 코드는 실행되지 않음
a.next();
// {value: 1, done: false}
a.next();
// {value: 2, done: false}
a.next();
// {value: 3, done: false}
a.next();
// {value: 'finish', done: true}
function* fn(){
yield 1;
yield 2;
yield 3;
return 'finish';
}
const a = fn();
a.next()
// {value: 1, done: false}
a.return('end');
// {value: 'end', done: true}
a.next()
// {value: undefined, done: true}
function* fn(){
try{
yield 1;
yield 2;
yield 3;
return 'finish';
}catch(e){
console.log(e);
}
}
const a = fn();
a.next()
// {value: 1, done: false}
a.throw(new Error('err'));
/*
VM417:8 Error: err
at <anonymous>:1:9
{value: undefined, done: true}
*/
a.next()
// {value: undefined, done: true}
Generator : iterable임
iterable : 반복 가능한 객체
iterable 조건
iterator : 메소드를 호출한 결과
iterator 조건
배열도 반복이 가능한데, iterable 일까??
배열을 만든 후 출력해보면, Symbol.iterator라는 메소드를 가지고 있다.
arr
// (5) [1, 2, 3, 4, 5]
it.next()
// {value: 1, done: false}
it.next()
// {value: 2, done: false}
it.next()
// {value: 3, done: false}
it.next()
// {value: 4, done: false}
it.next()
// {value: 5, done: false}
it.next()
// {value: undefined, done: true}
배열은 Symbol.iterator라는 메소드를 가지고 있고, 이 메소드가 반환하는 값이 iterator이므로, iterable하다고 할 수 있다.
즉, 배열은 반복 가능한 객체임
iterable --> for ... of
를 이용하여 순회 가능
for(let num of arr){
console.log(num)
}
// 1
// 2
// 3
// 4
// 5
배열 = iterable임
function* fn(){
yield 3;
yield 4;
yield 5;
}
const a = fn();
a[Symbol.iterator]() === a; // true
// generator는 iterable 객체이기 때문에 for...of 사용 가능
for (let num of a){
console.log(num);
}
// 3
// 4
// 5
문자열 = iterable임
const str = 'hello';
str[Symbol.iterator]
// ƒ [Symbol.iterator]() { [native code] }
const strng = str[Symbol.iterator]();
for (let s of strng) {
console.log(s);
}
// h
// e
// l
// l
// o
strng.next()
// {value: 'h', done: false}
strng.next()
// {value: 'e', done: false}
// next() 메소드를 사용하는 것도 가능
function* fn(){
const num1 = yield '첫 번째 숫자를 입력해주세요';
console.log(num1);
const num2 = yield '두 번째 숫자를 입력해주세요';
console.log(num2);
return num1 + num2;
}
const a = fn();
a.next(3);
// {value: '첫 번째 숫자를 입력해주세요', done: false}
// value 값 : yield 옆에 있는 값
a.next(1);
// 1
// next에 인수를 넣고 실행하면, 해당 값은 num1에 저장됨. 해당 값은 console.log()를 통해 보여짐
//{value: '두 번째 숫자를 입력해주세요', done: false}
a.next(5);
// 5
// {value: 6, done: true}
// 더 이상 yield가 없이 때문에 done: true로 변경됨
a.next();
// {value: undefined, done: true}
function* fn(){
let num = 0;
while(1){
yield num++;
}
}
const a = fn();
a.next();
// {value: 0, done: false}
a.next();
// {value: 1, done: false}
a.next();
// {value: 2, done: false}
function* gen1(){
yield 'w';
yield 'o';
yield 'r';
yield 'l';
yield 'd';
}
function* gen2(){
yield 'Hello, ';
yield* gen1(); // 다른 generator 함수 호출
yield '!';
}
const g = gen2();
g.next();
// {value: 'Hello, ', done: false}
g.next();
// {value: 'w', done: false}
g.next();
// {value: 'o', done: false}
g.next();
// {value: 'r', done: false}
g.next();
// {value: 'l', done: false}
g.next();
// {value: 'd', done: false}
g.next();
// {value: '!', done: false}
g.next();
// {value: undefined, done: true}
또는, 구조분해할당을 이용하여 다음과 같이 호출 가능
console.log(...gen2());
// Hello, w o r l d !