March 27, 2021
function* f1() {
yield 10;
yield 10;
return 'finished';
}
const gen = f1();
*
문자와 함께 정의된 함수와 그 함수가 반환하는 제너레이터 객체로 구성된다.yield
키워드를 사용하면 함수의 실행을 멈출 수 있다.function* f1() {
console.log('f1-1');
yield 10;
console.log('f1-2');
yield 20;
console.log('f1-3');
return 'finished';
}
const gen = f1(); // 제너레이터 객체 생성, 함수 실행되지 않는다.
console.log(gen.next()); // f1-1 { value: 10, done: false }
console.log(gen.next()); // f1-2 { value: 20, done: false }
console.log(gen.next()); // f1-3 { value: 'finished', done: true }
next
라는 메서드를 갖고 있다.const get = f1()
: f1()
제너레이터 함수를 실행해서 제너레이터 객체를 생성한다. 이 때, f1()
함수를 호출할 때 함수 내부가 전혀 실행되지 않는다. 그래서 f1-1
로그 조차도 출력되지 않는다.next
메서드를 호출해야 함수가 실행이 된다. (단, yield
를 만날 때까지만 실행한다.)yield
키워드를 만나면 그 값을 반환한다.next
메서드가 반환하는 값은 value
와 done
이라는 속성값을 가진 객체이다.return
키워드를 만나면 done
속성을 true
로 만든다.function* f1() {
try {
console.log('f1-1');
yield 10;
console.log('f1-2');
yield 20;
} catch(e) {
console.log('f1-catch', e);
yield 30;
console.log('f1-3');
yield 40;
console.log('f1-4');
}
}
const gen = f1();
console.log(gen.next());
console.log(gen.throw('some error'));
console.log(gen.next());
/*
f1-1
{ value: 10, done: false }
f1-catch some error
{ value: 30, done: false }
f1-3
{ value: 40, done: false }
f1-4
*/
next
호출 시 : f1-1
로그 출력, yield 10
에서 실행 멈춤.throw
호출 시 : 예외가 발생했기 때문에 catch
문으로 들어와서 f1-catch
로그 출력, yield 30
에서 실행 멈춤.next
호출 시 : f1-3
로그 출력, yield 40
에서 실행 멈춤next
호출 시 : f1-4
로그 출력, 종료next
메서드를 갖고 있다.next
메서드는 value
와 done
속성값을 가진 객체를 반환한다.done
속성값은 작업이 끝났을 때 참이 된다.Symbol.iterator
속성값으로 함수를 갖고있다.배열이 대표적인 iterable이다.
const arr = [10, 20, 30];
const iter = arr[Symbol.iterator]();
console.log(iter.next()); // { value: 10, done: false }
console.log(iter.next()); // { value: 20, done: false }
console.log(iter.next()); // { value: 30, done: false }
console.log(iter.next()); // { value: undefined, done: true }
function* f1() {
// ...
}
const gen = f1(); // 제너레이터 객체 생성
console.log(gen[Symbol.iterator]() === gen); // true
Symbol.iterator
라는 속성 값이 있고 그것을 실행시켰을 때 iterator가 반환되는데 이 iterator는 자기 자신이다.function* f1() {
yield 10;
yield 20;
yield 30;
}
for (const v of f1()) {
console.log(v); // 10 20 30
}
const arr = [...f1()];
console.log(arr); // [10, 20, 30]
next
메서드를 호출하면서 done
속성값이 참이 될 때까지 반복한다.done
속성값이 참이될 때까지 값을 펼친다.map
, filter
, take
와 같은 함수들을 구현할 수 있다.map
, filter
같은 것들은 새로운 배열 객체가 생성이 되어 반환된다.)Example
function* map(iter, mapper) {
for (const v of iter) {
yield mapper(v);
}
}
function* filter(iter, test) {
for (const v of iter) {
if (test(v)) {
yield v;
}
}
}
function* take(n, iter) {
for (const v of iter) {
yield v;
if (--n <= 0) return;
}
}
const values = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
const result = take(
3,
map(
filter(values, n => n % 2 === 0),
n => n * 10,
),
);
console.log([...result]); // [ 20, 40, 60 ]
console.log([...result])
부분과 같이 값이 필요한 순간에만 필요한 연산을 수행한다.Example
function* f1() {
const data1 = yield;
console.log(data1);
const data2 = yield;
console.log(data2);
}
const gen = f1();
gen.next();
gen.next(10); // 10
gen.next(20); // 20
next
메서드의 인수로 값을 입력하면 yield
의 반환값이 된다.Example
function* jessie() {
const myMessages = [
'Hello',
'My name is Jessie',
'I am FE Developer',
'Wow!',
];
for (const msg of myMessages) {
console.log('Laura: ', yield msg);
}
}
function laura() {
const myMessages = [
'',
'Hi',
'I am Laura',
'Me too',
];
const gen = jessie(); // 제너레이터 객체 생성
for (const msg of myMessages) {
console.log('Jessie: ', gen.next(msg).value);
}
}
laura();
/*
Jessie: Hello
Laura: Hi
Jessie: My name is Jessie
Laura: I am Laura
Jessie: I am FE Developer
Laura: Me too
Jessie: Wow!
*/
laura
함수에서 제너레이터 객체를 만들어서 next
메서드를 호출하고 있다.gen.next('').value
: Hello
반환 →Jessie: Hello
출력gen.next('Hi')
호출 → next
메서드의 인수로 값을 입력하면 yield
의 반환값이 된다.Laura: Hi
출력