본 내용은 10분 테코톡 파노님의 강의를 토대로 작성하였습니다.
1. Generator Function
- Generator Function은 Generator Instance를 생성
- new 키워드를 사용한 인스턴스 생성([[constructor]])이 아닌, 일반적인 함수호출([[call]])을 통해 인스턴스를 생성
- Generator 함수의 특별한 동작
function* generatorFunction() {};
const generator = generatorFunction();
typeof generator; // 'object'
Generator Syntax
- function* : Generator 함수 선언 키워드
- yield : Generator 함수 내부에서 사용하는 키워드
- next 메서드 호출 시, value로 반환할 값에 사용하는 키워드
- 다음 next가 호출될 때까지 해당 키워드에서 함수실행이 멈춤
- yield* : 또 다른 Iterable 객체를 위임해서 사용하는 키워드
function* generatorFunction() {
yield* [1, 2, 3];
}
const generator = generatorFunction();
for (const element of generator) {
console.log(element);
}
// 1 2 3 출력
2. Generator Instance
- Iterable 인터페이스와 Iterator 인터페이스를 동시에 구현한 객체
Generator Instacne의 Iterable Interface
- Iterable 인터페이스
- @@iterator (Symble.interator) 프로퍼티에 Iterator 객체인 자기자신을 반환하는 함수 저장
function* generatorFunction() {};
const generator = generatorFunction();
const iterator = generator[Symbol.iterator]();
console.log(generator === iterator); // true
Generator Instance의 Iterator Interface
- value와 done을 반환하는 next 메서드를 포함
function* generatorFunction() {
yield 1;
};
const generator = generatorFunction();
const iteratorResult = generator.next();
console.log(iteratorResult); // {value: 1, done: false}
Generator Instance의 Internal Slot
- Generator의 상태(실행 중인지, 중단됐는지 등) 정보가 [[GeneratorState]]에 저장
- 실행 컨텍스트가 [[GeneratorContext]]에 저장
- 실행이 중단된 Generator가 next()가 호출되면 중단 지점부터 다시 실행될 수 있는 이유
3. Lazy Evaluation
- 지연평가
- 계산의 결과값이 필요할 때까지 계산을 늦추는 기법
- 필요한 데이터를 필요한 순간에 생성
- Generator의 가장 큰 특징
무한수열 예시
- while 문으로 무한 반복문을 선언하더라도 yield로 인해서 함수 평가가 중지가 됨
function* genFunc() {
let i = 0;
while (true) {
yield i++;
}
}
const gen = genFunc();
// yield에서 함수 평가가 중지가 됨
console.log(gen.next()); // {value: 0, done: false}
console.log(gen.next()); // {value: 1, done: false}
console.log(gen.next()); // {value: 2, done: false}
4. 함수형 프로그래밍에서 Early Evaluation vs. Lazy Evaluation
Lazy Evaluation
- 필요한 2번의 순회만 진행
- 필요한 값만 효율적으로 계산할 수 있음
Object.prototype.lazyMap = lazyMap;
Object.prototpye.take = take;
// this의 element를 순회하는 함수
function* lazyMap(callback) {
for (const el of this) {
// callback이 적용된 element의 값만 yiled로써 iterator Result로 반환
yield callback(el);
}
}
// 전달 받은 값만큼 길이를 가지는 배열 result를 반환
function take(n = Infinity) {
const result = [];
for (const el of this) {
result.push(el);
if (result.length === n) break;
}
return result;
}
function callback(element) {
console.log('callback called!');
return element + 1
}
const arr = Array(10000).fill(1);
const mappedArr = arr.lazyMap(callback).take(2);
consoe.log(mappedArr);
// (2)callback called!
// [2, 2]
Early Evaluation
- 만 번의 순회를 진행하게 됨
...
const arr = Array(10000).fill(1);
const mappedArr = arr.map(callback).take(2);
console.log(mappedArr);
Reference
'programming study > JavaScript' 카테고리의 다른 글
ES6 & Babel (0) | 2021.10.18 |
---|---|
Scope & Closure (0) | 2021.10.12 |
Generator & Iterator (1) - Iteration Interface (0) | 2021.10.10 |
ES Modules (0) | 2021.09.28 |
불변성 (0) | 2021.09.18 |