티스토리 뷰
이선 브라운의 러닝 자바스크립트 책을 학습하고 기억해둘 만 한 부분을 야생학습하여 정리하였습니다.
이터레이터와 제너레이터는 ES6에서 새로 도입되었습니다.
이터레이터는 일종의 책갈피와 비슷한 개념입니다. 예를 들어 book이란 배열이 있고 이 배열의 각 요소는 책의 한 페이지를 나타내는 문자열이라고 칩시다.
const book = [ /* 문장 하나 씩 들어있는 문자열 배열 */ ];
// book 배열에 values 메서드를 써서 이터레이터를 만듭니다.
const it = book.values();
//이터레이터는 보통 it이란 이름으로 변수/상수 명을 짓습니다.
//읽기 시작
it.next(); // { value: /* book 배열의 첫번째 문장 */, done: false }
it.next(); // { value: /* book 배열의 두번째 문장 */, done: false }
it.next(); // { value: undefined, done: true }
이터레이터는 모두 독립적이기 때문에 새 이터레이터를 만들 때마다 처음부터 시작합니다. 또한 for ... of 루프를 사용하여 이터레이터 요소에 접근할 수 있습니다.
이터레이션 프로토콜
이터레이션 프로토콜은 모든 객체를 이터러블 객체로 바꿀 수 있습니다. 이터레이션 프로토콜은 클래스에 심볼 메서드 Symbol.iterator가 있고 이 메서드가 이터레이터처럼 동작하는 객체, 즉 value와 done 프로퍼티가 있는 객체를 반환하는 next 메서드를 가진 객체를 반환하면 그 클래스의 인스턴스는 이터러블 객체라는 뜻입니다.
class Log {
constructor() {
this.messages = [];
}
add(message) {
this.messages.push({message, timestamep: Date.now()});
}
[Symbol.iterator]() {
return this.messages.values();
}
}
//로그 클래스를 이터러블 객체로 만들어 for...of 루프로 순회합니다.
for(let entry of log) {
console.log(`${entry.message + ${entry.timestamp}`);
}
//이터레이터를 직접 만들 수도, done에서 true를 반환하지 않는 무한한 데이터를 만들 수도 있습니다.
class FibonacciSequence {
[Symbol.iterator]() {
let a = 0, b = 1;
return {
next() {
let rval = { value: b, done: false };
b += a;
a = rval.value;
return rval;
}
};
}
}
제너레이터
제네레이터란 이터레이터를 활용해 자신의 실행을 제어하는 함수입니다. 일반적인 함수와는 달리 두가지 새로운 개념을 가지고 있는데 첫째로는 제네레이터는 언제든 호출자에게 제어권을 넘길(yield)할 수 있습니다. 다음으로는 제네레이터는 호출한 즉시 실행되지 않고 대신 이터레이터를 반환하며 이터레이터의 next 메서드를 호출함에 따라 실행됩니다.
제네레이터를 만들 때는 function 키워드 뒤에 *을 붙입니다. 또한 return 외에 yield 키워드를 사용할 수 있습니다.
function* rainbow() {
yield 'red';
yield 'orange';
yield 'yellow';
//.....
}
const it = rainbow();
it.next(); // { value: "red", done: false }
//...
yield는 표현식이므로 반드시 어떤 값으로 평가되며 이를 이용하여 제너레이터와 호출자 사이에서 양방향 통신이 가능합니다.
function* interrogate() {
const name = yield "What is your name?";
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('Eraser'); // { value: "What is your favorite color?", done: false }
it.next('purple'); // // { value: "Eraser's favorite color is purple", done: false }
제너레이터에서 return 문을 사용하면 done은 true가 되고 value 프로퍼티는 return문이 반환하는 값이 되나, done이 true면 value 프로퍼티에 주의를 기울이지 않기 때문에 for...of 루프에서는 제대로 출력이 되지 않음을 감안하여 제너레이터에 return을 쓸 때는 반환값을 쓰지 않는 습관을 들이는 편이 좋습니다.
'Running JS 요약' 카테고리의 다른 글
JS - 비동기적 프로그래밍 (0) | 2021.01.31 |
---|---|
JS - 함수와 추상적 사고 (0) | 2021.01.21 |
JS - 맵과 셋 / 예외와 에러 처리 (0) | 2021.01.18 |
JS - 객체와 객체지향 프로그래밍 (0) | 2021.01.11 |
JS - 배열 (0) | 2021.01.06 |