06-2. 반복기와 생성기

euNung·2022년 6월 7일
0

타입스크립트

목록 보기
6/10
  • yield
    : 마치 return 키워드처럼 값을 반환
    : function* 키워드를 사용한 함수에서만 호출 가능
    : 반복기를 자동으로 만들어 줌
    : 반복기 제공자 역할도 수행

✅ function* 키워드로 만든 함수를 '생성기(generator)'라고 한다.
=> 화살표 함수로는 생성기를 만들 수 없음

function* generator() {
    console.log('generator started...')
    let value = 1
    while(value < 4) {
        yield value++
    }
    console.log('generator finished...')
}

for (const value of generator()) {
    console.log(value)
}

/* 실행결과
generator started...
1
2
3
generator finished...
*/
  • 생성기가 동작하는 방식을 '세미코루틴(semi-corution, 반협동루틴)'이라고 함
    - 세미코루틴: 타입스크립트처럼 단일 스레드로 동작하는 프로그램이 언어가 마치 다중 스레드로 동작하는 것처럼 보이게 하는 기능(ex) setInderval)


  • 반복기 제공자의 메서드로 동작하는 생성기 구현
class IterableUsingGenerator<T> implements Iterable<T> {
    constructor(private values: T[] = [], private currentIndex: number = 0) {}
    [Symbol.iterator] = function* () {
        yield this.values[this.currentIndex++]
    }
}

for (const item of new IterableUsingGenerator([1, 2, 3])) {
    console.log(item)
}

for (const item of new IterableUsingGenerator(['hello', 'world', '!'])) {
    console.log(item)
}
let numbers = {
  *[Symbol.iterator]() {
    for (let n = 1; n <= 10; n++) {
      yield n
    }
  }
}

let iterator = numbers[Symbol.iterator]()
console.log(iterator.next());	// { value: 0, done: false }
console.log(iterator.next());	// { value: 1, done: false }
console.log(iterator.next());	// { value: 2, done: false }
  • yield 반환값
    : 반복기의 next 메서드 호출 때 매개변수에 전달하는 값
function* gen() {
    let count = 5
    let select = 0
    while(count--) {
        select = yield `you select ${select}`
    }
}

const random = (max, min=0) => Math.round(Math.random() * (max-min) + min)

const iterator4 = gen()
while(true) {
    const { value, done } = iterator4.next(random(10, 1))
    if(done) break
    console.log(value)
}

/* 실행 결과
you select 0
you select 7
you select 2
you select 10
you select 6
*/

=> 이전에 next 메서드가 전달한 값이 다시 gen함수의 내부 로직에 의해 현재의 value값이 되어 출력

  • yield*
    : 다른 생성기나 배열을 대상으로 동작
    ( yield는 단순히 값을 대상으로 동작 )
  function* gen12() {
      yield 1
      yield 2
  }

  function* gen12345() {
      yield* gen12()
      yield* [3, 4]
      yield 5
  }
  for (const value of gen12345()) {
      console.log(value)
  }

  /* 실행결과
  1
  2
  3
  4
  5
  */
  • 제너레이터의 타입 명시
function* createNumbers(): IterableIterator<number> {
  let n = 0
  while(1) {
    yield n++
  }
}

let numbers = createNumbers()
numbers.next()    // {value: 0, done: false}로 평가
numbers.next()    // {value: 1, done: false}로 평가
numbers.next()    // {value: 2, done: false}로 평가
profile
프론트엔드 개발자

0개의 댓글