[3/23] 제너레이터 & 이터러블/이터레이터 프로토콜

릿·2023년 3월 30일
0

CS스터디

목록 보기
14/18

1. 제너레이터

1. 정의

  • 코드블록의 실행을 일시 중지했다가 필요한 시점에 재개할 수 있는 특수한 함수
  • 이터레이터이면서 이터러블을 생성하는 함수

2. 일반함수와의 차이

  • 제너레이터 함수는 함수 호출자에게 함수 실행의 제어권을 양도할 수 있음
  • 제너레이터 함수는 함수 호출자와 함수의 상태를 주고받을 수 있음
  • 제너레이터 함수를 호출하면 제너레이터 객체를 반환함

3. 함수 정의 방법

  • 제너레이터 함수는 function* 키워드로 선언하고, 하나 이상의 yield 표현식을 포함함
  • 애스터리스크(*)의 위치는 function키워드와 함수 이름 사이라면 어디든지 상관없지만 일관성 유지를 위해 function키워드 바로 뒤에 붙이는 것을 권장함
  • 제너레이터 함수는 화살표 함수와 new연산자와 함께 생성자 함수로 호출할 수 없음
// 제너레이터 함수 선언문
function* genDecFunc() {
  yield 1;
};

// 제너레이터 함수 표현식
const genExpFunc = function* () {
  yield 1;
};

// 제너레이터 메서드
const obj = {
  * genObjMethod() {
    yield 1;
  }
};

// 제너레이터 클래스 메서드
class MyClass {
  * genClsMethod() {
    yield 1;
  }
}

4. 제너레이터 객체

  • 제너레이터 함수를 호출하면 제너레이터 객체를 생성해 반환
  • 제너레이터 객체는 next메서드를 갖는 이터레이터이지만, 이터레이터에는 없는 return, throw메서드를 가짐
  • next메서드를 호출하면 제너레이터 함수의 yield표현식까지 코드 블록을 실행하고 yield된 값을 value프로퍼티 값으로, false를 done프로퍼티 값으로 갖는 iterator result객체를 반환함
  • return메서드를 호출하면 인수로 전달받은 값을 value프로퍼티 값으로, true를 done프로퍼티 값으로 갖는 iterator result객체를 반환함
  • throw메서드를 호출하면 인수로 전달받은 에러를 발생시키고, undefined를 value프로퍼티 값으로, true를 done프로퍼티 값으로 갖는 iterator result객체를 반환
function* genFunc() {
  try {
    yield 1;
    yield 2;
    yield 3;
  } catch (e) {
    console.error(e);
  }
}

const generator = genFunc();


// return메서드를 활용
console.log(generator.next()); // {value: 1, done: false}
console.log(generator.return('End!')); // {value: 'End!', done: true}

// throw메서드를 활용
console.log(generator.next()); // {value: 1, done: false}
console.log(generator.throw('Error!')); // {value: undefined, done: true}

5. 제너레이터의 일시 중지와 재개

  • yield키워드는 제너레이터 함수의 실행을 일시 중지시키거나 yield키워드 뒤에 오는 표현식의 평가 결과를 제너레이터 함수 호출자에게 반환함
  • 제너레이터 객체의 next메서드에 전달한 인수는 제너레이터 함수의 yield표현식을 할당받는 변수에 할당됨
function* genFunc() {
  yield 1;
  yield 2;
  yield 3;
}

const generator = genFunc();

console.log(generator.next()); // {value: 1, done: false}
console.log(generator.next()); // {value: 2, done: false}
console.log(generator.next()); // {value: 3, done: false}
console.log(generator.next()); // {value: undefined, done: true}

6. 제너레이터의 활용

  • 제너레이터 함수를 사용하면 간단히 이터러블을 구현할 수 있음
    예시) 이터레이션 프로토콜을 준수하여 무한 피보나치 수열을 생성하는 함수 구현

7. 비동기 처리

함수의 비동기 처리도 제네레이터를 통해 구현할 수 있지만 ES8의 async/await가 완전히 그 기능을 대체하고 있음

2. 이터러블

1. 이터러블이란?

  • 이터러블 프로토콜을 준수한 객체
  • Symbol.iterator를 프로퍼티 키로 사용한 메서드를 직접 구현하거나 프로토타입 체인을 통해 상속받은 객체
  • 이터러블인지 확인하는 방법
const isIterable = v => v !== null && typeof v[Symbol.iterator] === 'function';

isIterable([]); // -> true
isIterable(''); // -> true
isIterable(new Map()); // -> true
isIterable(new Set()); // -> true
isIterable({}); // -> false

2. 이터레이터

  • 이터러블 Symbol.iterator메서드를 호출하면 이터레이터 프로토콜을 준수한 이터레이터 반환
  • next메서드를 가짐
  • next메소드를 호출할 때 iterator result객체를 반환한다면 이터레이터 프로토콜을 충족한 이터레이터임

next메서드

  • 이터러블의 각 요소를 순회하기 위한 포인터 역할을 함
  • iterator result객체 반환
  • value 프로퍼티 : 현재 순회중인 이터러블의 값
  • done 프로퍼티 : 이터러블 순회 완료 여부
const array = []];

const iterator = array[Symbol.iterator]();

console.log(iterator.next()); // { value: 1, done: false }
console.log(iterator.next()); // { value: 2, done: false }
console.log(iterator.next()); // { value: 3, done: false }
console.log(iterator.next()); // { value: undefined, done: true }

3. 유사 배열 객체

  • 인덱스로 프로퍼티 값에 접근 가능
  • length프로퍼티를 가짐
  • for문 순회 가능
  • 일반 객체이므로 for...of으로 순회 불가
  • Array.from으로 배열로 변환가능

4. 이터레이터 프로토콜이란?

  • Iteration Protocol = Iterable Protocol = Iterator Protocol
  • ES6에서 새로 도입된 데이터 컬렉션 객체(대표적으로 Array)를 순회하기 위한 Protocol(정의된 규칙)이다. 이 프로토콜을 준수한 객체만이 for of 문으로 순회할 수 있고 Spread문법의 피연산자가 될 수 있다.

5. 빌트인 이터러블 (ES6 기준)

Array, String, Map, Set, TypedArray(Int8Array, Uint8Array, Uint8ClampedArray, Int16Array, Uint16Array, Int32Array, Uint32Array, Float32Array, Float64Array), DOM data structure(NodeList, HTMLCollection), Arguments

profile
항상 재밌는 뭔가를 찾고 있는 프론트엔드 개발자

0개의 댓글