JavaScript ES6 - 3. 제너레이터와 이터레이터


유인동님의 함수형 프로그래밍과 JavaScript ES6+ 인프런 강의를 듣고 개인적으로 정리한 내용입니다.
함수형 프로그래밍과 JavaScript ES6 제너레이터와 이터레이터에 대해서 설명한다.

제너레이터와 이터레이터

  • 제너레이터는 이터레이터이자 이터러블을 생성하는 함수(이터레이터를 리턴하는 함수)
  • 제네레이터의 리턴값은 마지막 done에 값이 true 일때 전달되고, for…of 문에는 적용이 안된다.
  • 제너레이터는 순회하는 함수에 문장으로 구현할 수 있다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
function* gen() {
yield 1;
if (false) yield 2;
yield 3;
return 100;
}

let iter = gen(); // 제너레이트를 실행한 결과가 이터레이터
console.log(iter[Symbol.iterator]() == iter);
console.log(iter.next());
console.log(iter.next());
console.log(iter.next());
console.log(iter.next());

for (const a of gen()) {
console.log(a);
}
console
1
2
3
4
5
6
7
> true
> {value: 1, done: false}
> {value: 3, done: false}
> {value: 100, done: true}
> {value: undefined, done: true}
> 1
> 3

odds

제너레이터를 이용해서 홀수만 발생시키는 예제

직접 입력하여 홀수 발생

1
2
3
4
5
6
7
8
9
10
11
function* odds() {
yield 1;
yield 3;
yield 5;
}

let iter2 = odds();
console.log(iter2.next());
console.log(iter2.next());
console.log(iter2.next());
console.log(iter2.next());
console
1
2
3
4
> {value: 1, done: false}
> {value: 3, done: false}
> {value: 5, done: false}
> {value: undefined, done: true}

해당 값을 받아 처리

10을 입력하여 10보다 작은 홀수를 출력한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
function* odds(l) {
for (let i = 0; i < l; i++) {
if (i % 2) {
yield i;
}
}
}

let iter2 = odds(10);
console.log(iter2.next());
console.log(iter2.next());
console.log(iter2.next());
console.log(iter2.next());
console.log(iter2.next());
console.log(iter2.next());
console
1
2
3
4
5
6
> {value: 1, done: false}
> {value: 3, done: false}
> {value: 5, done: false}
> {value: 7, done: false}
> {value: 9, done: false}
> {value: undefined, done: true}

무한수열을 통해 홀수만 출력

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
function* infinity(i = 0) {
while (true) {
yield i++;
}
}

function* odds(l) {
for (const a of infinity(1)) {
if (a % 2) {
yield a;
}
if (a == l) {
return;
}
}
}

let iter2 = odds(10);
console.log(iter2.next());
console.log(iter2.next());
console.log(iter2.next());
console.log(iter2.next());
console.log(iter2.next());
console.log(iter2.next());
console
1
2
3
4
5
6
> {value: 1, done: false}
> {value: 3, done: false}
> {value: 5, done: false}
> {value: 7, done: false}
> {value: 9, done: false}
> {value: undefined, done: true}

limit 제네레이터 이용하여 순회하는 함수 생성

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
// 무한 수열
function* infinity(i = 0) {
while (true) {
yield i++;
}
}

function* limit(l, iter) {
for (const a of iter) {
yield a;
if (a == l) {
return;
}
}
}

function* odds(l) {
for (const a of limit(l, infinity(1))) {
if (a % 2) {
yield a;
}
}
}

let iter2 = odds(10);
console.log(iter2.next());
console.log(iter2.next());
console.log(iter2.next());
console.log(iter2.next());
console.log(iter2.next());
console.log(iter2.next());
console
1
2
3
4
5
6
> {value: 1, done: false}
> {value: 3, done: false}
> {value: 5, done: false}
> {value: 7, done: false}
> {value: 9, done: false}
> {value: undefined, done: true}

for…of, 전개 연산자, 구조 분해, 나머지 연산자

odds에서 만든 제네러이터를 이용해서 실행

for…of

1
2
3
for (const a of odds(14)) {
console.log(a);
}
console
1
2
3
4
5
6
7
> 1
> 3
> 5
> 7
> 9
> 11
> 13

전개 연산자

1
2
console.log(...odds(10));
console.log([...odds(10)], ...odds(20));
console
1
2
> 1 3 5 7 9
> (5) [1, 3, 5, 7, 9] 1 3 5 7 9 11 13 15 17 19

구조 분해

1
2
3
const [head, ...tail] = odds(5);
console.log(head);
console.log(tail);
console
1
2
> 1
> (2) [3, 5]

나머지 연산자

1
2
3
const [head, ...tail] = odds(5);
console.log(head);
console.log(tail);
console
1
2
3
> 1
> 3
> (3) [5, 7, 9]

제너레이터와 이터레이터 소스코드

참조