제너레이터는 이터레이터이자 이터러블을 생성하는 함수를 말한다. 즉 이터레이터를 리턴하는 함수이다.
제너레이터는 일반함수에서 앞에 *을 붙여서 제너레이터 함수를 만든다. 또 제너레이터는 이터레이터를 반환한다.
아래와 같이 제너레이터가 있다고 했을 때 제너레이터를 실행한 결과는 이터레이터이다. 이터레이터를 아래코드와 같이 실행 해보자. 제너레이터를 통해 쉽게 이터레이터를 만들 수 있다.
<script>
function* gen() {
yield 1;
yield 2;
yield 3;
}
let iter = gen();
log(iter.next());
log(iter.next());
log(iter.next());
log(iter.next());
</script>
=>
{value: 1, done: false}
index.html:14 {value: 2, done: false}
index.html:15 {value: 3, done: false}
index.html:16 {value: undefined, done: true}
이터레이터이자 이터러블이기도 한데 이터레이터는 심볼 이터레이터를 가지고 있고 심볼 이터레이터의 실행결과는 자기자신이다. 그러니까 제너레이터는 well-formed 이터레이터를 리턴하는 함수이다. 그리고 제너레이터의 yield를 통해서 몇 번의 next를 통해 값을 꺼내줄 것인지를 정할 수 있다.
let iter = gen();
log(iter[Symbol.iterator]() == iter);
log(iter.next());
log(iter.next());
log(iter.next());
log(iter.next());
=>
true
index.html:14 {value: 1, done: false}
index.html:15 {value: 2, done: false}
index.html:16 {value: 3, done: false}
index.html:17 {value: undefined, done: true}
그리고 제너레이터를 사용하게 되면 역시 제너레이터의 실행결과가 이터러블이자 이터레이터이기 때문에 아래와 같이 순회를 할 수 있다.
let iter = gen();
log(iter[Symbol.iterator]() == iter);
log(iter.next());
log(iter.next());
log(iter.next());
log(iter.next());
for (const a of gen()) log(a);
=>
true
index.html:14 {value: 1, done: false}
index.html:15 {value: 2, done: false}
index.html:16 {value: 3, done: false}
index.html:17 {value: undefined, done: true}
index.html:19 1
index.html:19 2
index.html:19 3
그리고 제너레이터에서는 마지막에 리턴값을 만들 수 있다.
조심할 것은 순회할 때 리턴값은 제외하고 순회가 이루어진다. 리턴 값은 마지막에 done 할때 나오는 값이라고 생각하자.
<script>
function* gen() {
yield 1;
yield 2;
yield 3;
return 100;
}
let iter = gen();
log(iter[Symbol.iterator]() == iter);
log(iter.next());
log(iter.next());
log(iter.next());
log(iter.next());
for (const a of gen()) log(a);
</script>
=>
true
index.html:15 {value: 1, done: false}
index.html:16 {value: 2, done: false}
index.html:17 {value: 3, done: false}
index.html:18 {value: 100, done: true}
index.html:20 1
index.html:20 2
index.html:20 3
그리고 제너레이터는 순회할 값을 문장으로 표현하는 것이라고도 할 수 있다. 그래서 아래코드를 작성하면 순회가 이루어지는 함수를 만들 수 있다. 자바스크립트에서는 어떠한 값이든 이터러블이면 순회할 수 있다.
그런데 제너레이터는 이런 문장을 값으로 만들 수 있고 문장을 통해서 순회할 수 있는 값을 만들 수 있기 때문에 자바스크립트에서는 제너레이터를 통해서 어떠한 상태나 어떠한 값이든 사실상 순회할 수 있게 만들 수 있다.
굉장히 상징적이다.
제너레이터라는 문장을 통해 순회할 수 값을 만들 수 있다는 것은 어떠한 값도 순회할 수 있는 형태로 제너레이터라는 문장을 통해 조작할 수 있으며 제너레이터를 통해서 굉장히 다양한 값들을 순회할 수 있는 이터러블을 쉽게 그리고 프로그래머가 로직을 만들면서 순회를 시킬 수 있다는 것이다.
<script>
function* gen() {
yield 1;
if (false) yield 2;
yield 3;
}
let iter = gen();
log(iter[Symbol.iterator]() == iter);
log(iter.next());
log(iter.next());
log(iter.next());
log(iter.next());
for (const a of gen()) log(a);
</script>
=>
true
index.html:14 {value: 1, done: false}
index.html:15 {value: 3, done: false}
index.html:16 {value: undefined, done: true}
index.html:17 {value: undefined, done: true}
index.html:19 1
index.html:19 3
<출처 : 유인동 함수형 프로그래밍과 JavaScript ES6+>
https://www.inflearn.com/course/functional-es6/dashboard
함수형 프로그래밍과 JavaScript ES6+ - 인프런 | 강의
ES6+와 함수형 프로그래밍을 배울 수 있는 강의입니다. 이 강좌에서는 ES6+의 이터러블/이터레이터/제너레이터 프로토콜을 상세히 다루고 응용합니다. 이터러블을 기반으로한 함수형 프로그래밍,
www.inflearn.com
'JavaScript > 함수형 프로그래밍과 JavaScript ES6+' 카테고리의 다른 글
map, filter, reduce(map) (0) | 2021.08.17 |
---|---|
odds(제너레이터와 이터레이터) & for of etc.. (0) | 2021.08.17 |
사용자 정의 이터러블, 이터러블/이터레이터 프로토콜 정의 & 전개 연산자 (0) | 2021.08.17 |
Array, Set, Map을 통해 iterable/iterator protocol 알아보기 (0) | 2021.08.17 |
es6에서 순회, iterable: iterator protocol(기존과 달라진 es6에서의 list 순회) (0) | 2021.08.17 |