function*
키워드로 정의되며, 호출 시 즉시 실행되지 않고 이터레이터(Iterator) 객체를 반환한다.
iterable
- JavaScript에서
iterable
은 반복 가능한 객체를 의미하며,for...of
루프나 전개 연산자(...
) 등과 같은 반복문에서 사용할 수 있는 객체이다.- 이 반복 가능한 객체(
iterable
한 객체)는 항상Symbol.iterator()
메소드를 구현하고 있어야 하며, 이 메소드는 객체가 어떻게 반복될지 정의한다.
iterator
- 반복 작업을 제어하는 객체로, 반복되는 시퀀스의 값을 하나씩 반환할 수 있다.
next()
메서드를 호출할 때마다 순차적으로 값을 반환하며, 반복이 끝나면done: true
가 반환된다.
iterator
객체가 갖고있는 next()
메소드를 사용하면, 가장 가까운 yield
키워드를 만날 때까지 코드를 실행할 수 있다.function* myGenerator() {
yield 1;
yield 2;
yield 3;
}
function*
키워드와 함께 yield
키워드를 사용해 값을 생성한다.function* fn() {
console.log(1);
yield 1;
console.log(2);
yield 2;
console.log(3);
console.log(4);
yield 3;
console.log(5);
return "finish!!";
}
// iterator한 제너레이터 객체가 반환됨.
// 이 객체는 내부적으로 next()메소드를 가지고 있어, 사용 가능
const a = fn();
// 1 출력 -> next()는 {value:1, done: false} 반환 후 출력
console.log(a.next());
// 2 출력 -> next()는 {value:2, done: false} 반환 후 출력
console.log(a.next());
// 3,4 출력 -> next()는 {value:3, done: false} 반환 후 출력
console.log(a.next());
// 5 출력 -> next()는 {value: finish!!, done: true} 반환 후 출력
console.log(a.next());
// next()는 {value: undefined, done: true} 반환 후 출력
console.log(a.next());
next()
메서드를 호출해 하나씩 값을 얻을 수 있다.function* func() {
console.log(11);
yield 1;
console.log(22);
yield 2;
console.log(33);
console.log(44);
yield 3;
console.log(55);
return "finish!!";
}
const a = func();
// 11 출력 -> next()는 {value:1, done: false} 반환 후 출력
console.log(a.next());
// 22 출력 -> next()는 {value:2, done: false} 반환 후 출력
console.log(a.next());
// 33,44 출력 -> next()는 {value: undefined, done: true} 반환 후 출력
console.log(a.return());
// iterator.next().return() 사용으로 함수 실행이 종료됨
// {value: undefined, done: true} 반환 후 출력
console.log(a.next());
func().return()
를 사용하면, 즉시 done은 true
가 되고, value는 undefined
가 된다.iterator.next().return()
을 사용하면, 이후 yield
키워드를 만날 때까지 함수 내부의 코드를 실행하는 것이 아니라, 바로 그 즉시 함수 실행을 종료하기 때문에 value가 undefined
가 된다.
function* infiniteSequence() {
let i = 0;
while (true) {
yield i++;
}
}
const seq = infiniteSequence();
console.log(seq.next().value); // 0
console.log(seq.next().value); // 1
iterable
객체 생성function* range(start, end) {
for (let i = start; i <= end; i++) {
yield i;
}
}
for (let value of range(1, 5)) {
console.log(value); // 1, 2, 3, 4, 5
}
iterable
객체이므로 for...of
루프에서 사용할 수 있다.yield
를 사용해 중간 중간 작업을 멈추고 다시 시작할 수 있어, 비동기 흐름을 관리하기에도 좋다.