제너레이터

김준엽·2022년 6월 28일
0

JavaScript

목록 보기
5/5

제너레이터(Generator)

제너레이터 함수는 이터러블을 생성하는 함수입니다. 일반 함수와 같이 함수 코드 블록을 한 번에 실행하지 않고 함수 코드 블록 실행을 일시 중지했다가 필요한 시점에 재시작하는 함수입니다. function* 키워드로 선언, 하나 이상의 yield문 포함, return문은 없어도 됩니다.

function* gen() {
  yield 1
  if (false) yield 2
  yield 3
  return 100 // done: true일 때 반환하는 값, 하지만 for of로 순회할 때 나오지는 않습니다.
}

const iter = gen()
console.log(iter[Symbol.iterator]() === iter) // true
console.log(iter.next()) // {value: 1, done: false}
console.log(iter.next()) // {value: 3, done: false}
console.log(iter.next()) // {value: 100, done: true}, return 값

for (const a of gen()) console.log(a) // 1 3

gen() 함수 결과로 제너레이터 객체 iter를 반환합니다. iter 는 이터러블이면서 이터레이터인 객체입니다. 위 제너레이터 함수를 보면 문장을 통해 순회할 수 있는 값을 만들 수 있습니다. 이건 자바스크립트에서 어떠한 값이든지 순회할 수 있다는 것을 의미합니다.

제너리이터 함수 호출 결과물은 제너레이터 객체라고 하며 이터러블(iterable)이면서 이터레이터(iterator)입니다.


함수형 프로그래밍 단계적 변화

1단계

function* odds(l) {
  for (let i = 0; i < l; i++) {
    if (i % 2) yield i
  }
}

for (const a of odds(10)) console.log(a) // 1 3 5 7 9

위 함수는 전달인자에 따라 홀수를 출력하는 함수입니다. 이 함수를 선언적으로 변화시켜보겠습니다. 바로 제너레이터를 이용하겠습니다.


2단계

//next로 평가할 때만 동작하기 때문에 브라우저가 과부하 걸리는 일은 없습니다.
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 // 선언적으로 변경가능한 포인트
  }
}

for (const a of odds(10)) console.log(a) // 1 3 5 7 9

무한으로 숫자를 증가하는 제너레이터 함수를 만들어 for ...of를 이용했습니다. 여기서 좀 더 선언적으로 변경할 수 있습니다. infinity제너레이터 함수는 필요한 시점에 시작하기 때문에 브라우저에 과부하 없이 동작할 수 있습니다.


3단계

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
  }
}

for (const a of odds(10)) console.log(a) // 1 3 5 7 9

반복종료 시점을 결정하는 제너레이터 함수를 limit를 구현했습니다. 여기서 모든 제너레이터 함수들은 각 목적에 맞는 값만 반환하는 이터러블을 생성합니다.


참고

Generator

profile
프론트엔드 개발자

0개의 댓글