chapter12. 이터레이터와 제너레이터

이터레이터iterator : ‘지금 어디 있는지’ 파악할 수 있도록 도움 ex)배열

  • values() 메서드를 써서 이터레이터를 만들 수 있다.
  • next() 메서드를 써서 호출할 수 있다.
  • 이터레이터가 끝까지 진행하면 뒤로 돌아가서 다른 데이터를 제공할 수 없다.
  • 이터레이터는 모두 독립적이다. 즉 새 이터레이터를 만들 때마다 처음에서 시작한다.
  • 각각 다른 요소를 가리키는 이터레이터 여러 개를 동시에 사용 가능하다.
이터레이터
1
2
3
4
5
6
7
const book = [
"1page","2page","3page","4page"
];

const it = book.values(); //이터레이터 생성
it.next(); //이터레이터 호출 //{value: "1page", done: false}
it.next(); // {value: "2page", done: false}

12.1 이터레이션 프로토콜

  • 이터레이터 프로토콜은 모든 객체를 이터러블iterable 객체로 바꿀 수 있다.
  • 이터레이션 프로토콜은 클래스에 심볼 메서드 Symbol.iterator가 있고,
    이 메서드가 이터레이터처럼 동작하는 객체, 즉 value와 done 프로퍼티가 있는 객체를 반환하는 next() 메서드를 가진 객체를 반환한다면 그 클래스의 인스턴스는 이터러블 객체란 뜻이다.
이터레이션_프로토콜
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
/*
메시지에 타임스탬프를 붙이는 로그 클래스
*/
class Log{
constructor(){
this.messages = [];
}
add(message){
this.messages.push({message,timestamp:Date.now()});
}
[Symbol.iterator](){
return this.messages.values();
}
}

const log = new Log();
log.add("first");
log.add("second");
log.add("third");

for(let entry of log){
console.log(`${entry.message} @ ${entry.timestamp}`);
}

/*
first @ 1563976491610
second @ 1563976491610
third @ 1563976491610
*/

이터레이터는 무한한 데이터에도 사용할 수 있다.

피보나치수열
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
32
//피보나치수열
class FibonacciSequence{
[Symbol.iterator](){
let a = 0 , b = 1;
return{
next(){
let rval = {value:b, done:false};
b += a;
a = rval.value;
return rval;
}
}
}
}

const fib = new FibonacciSequence(); //인스턴스 생성
let i = 0;
for(let n of fib){
console.log(n);
if(++i >9) break; // 무한루프에서 벗어나게 10회 계산한뒤 빠져나옴
}
/*
1
2
3
5
8
13
21
34
55
*/

12.2 제너레이터

제너레이터 : 이터레이터를 사용해 자신의 실행을 제어하는 함수

  • 제너레이터 만들때 function 키워드 뒤에 애스터리스크(*)를 붙인다.
  • return 이외에 yield 키워드를 쓸 수 있다.

제너레이터의 두 가지 새로운 개념

  • 1) 제너레이터는 함수의 실행을 개별적 단계로 나누어 함수의 실행을 제어한다.
  • 2) 실행 중인 함수와 통신한다.

제너레이터의 두 가지 예외

  • 1) 제너레이터는 언제든 호출자에게 제어권을 넘길 수 있다.
  • 2) 제너레이터는 호출한 즉시 실행되지는 않는다.
    대신 이터레이터를 반환하고, 이터레이터의 next() 메서드를 호출함에 따라 실행된다.
제너레이터
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
/* 무지개 색깔을 반환하는 제너레이터 생성 */
function* rainbow(){//* 기호는 제너레이터 문법
yield 'red';
yield 'orange';
yield 'yellow';
yield 'green';
yield 'blue';
yield 'indigo';
yield 'violet';
}

const it = rainbow(); //함수호출

for(let color of it){
console.log(color);
}
/*
red
orange
yellow
green
blue
indigo
violet
*/
제너레이터를 호출하면 이터레이터를 얻는다.
함수를 호출한 다음 이터레이터를 써서 단계별로 진행한다.

12.2.1 yield 표현식과 양뱡향 통신

  • yield 표현식을 통해 양뱡향 통신이 이뤄진다.
  • yield 표현식의 값은 호출자가 제너레이터의 이터레이터에서 next를 호출할 때 제공하는 매개변수이다.
대화_이어나가기
1
2
3
4
5
6
7
8
9
10
11
12
// yield 표현식과 양뱡향 통신
//대화_이어나가기 제너레이터 생성

function* interrogate(){
const name = yield 'what is your name?'; //let it = itterrogate();
const color = yield 'what is your favorite color?';
return `${name}'s favorite color is ${color}`;
}
const it = interrogate();
it.next(); //{value: "what is your name?", done: false}
it.next("Ethan"); //{value: "what is your favorite color?", done: false}
it.next("red"); //{value: "Ethan's favorite color is red", done: true}
  • 제너레이터를 호출하면 호출자가 함수의 실행을 제어할 수 있다.
  • 제너레이터는 화살표 표기법으로 만들 수 없으며 반드시 function*을 써야한다.

12.2.2 제너레이터와 return

  • yield문은 제너레이터의 마지막 문이여서 제너레이터를 끝내지 않는다.
  • 제너레이터에서 return 문을 사용하면, 그 위치와 관계없이 done은 true가 되고, value프로퍼티는 return이 반환하는 값이 된다.
제너레이터와_return
1
2
3
4
5
6
7
8
9
10
11
//제너레이터와 return
function* abc(){
yield 'a';
yield 'b';
return 'c';
}

const it = abc();
it.next(); //{value: "a", done: false}
it.next(); //{value: "b", done: false}
it.next(); //{value: "c", done: true}

제너레이터에서 중요한 값을 return으로 반환하지 말아야한다.
제너레이터가 반환한 값을 사용할 때는 yield로 쓰고,
return은 제너레이터를 중간에 종료할 떄만 사용

Comentarios

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×