제너레이터는 ES6에 도입된 특수한 함수다. 함수 호출자가 함수 실행을 제어할 수 있고, 함수 호출자와 함수 상태를 주고받을 수도 있다. 이런 특징 때문에 제너레이터 함수에선 코드 블록의 실행을 잠시 멈췄다가 필요한 시점에 재개할 수 있다. 일반 함수는 0~1개 값만 반환할 수 있지만, 제너레이터 함수는 여러개의 값을 필요에 따라 하나씩 반환할 수 있다.

제너레이터 함수의 특징


  1. 함수 호출자에게 함수 실행의 제어권을 양도(yield)할 수 있다
  2. 함수 호출자와 함수 상태를 주고받을 수 있다
  3. 제너레이터 함수를 호출하면 제너레이터 객체를 반환한다

제너레이터 함수 정의 방법


<aside> 💡 제너레이터 함수는 이터러블이다. 따라서 함수 자체에 전개 문법을 사용할 수도 있다.

</aside>

제너레이터 함수는 function* 키워드로 선언하고 함수 본문엔 1개 이상의 yield 표현식을 포함한다. 나머진 일반 함수를 정의하는 것과 동일하다. * 기호는 애스터리스크(Asterisk)라고 부르며 function 키워드와 함수 이름 사이라면 어디에 붙여도 상관없다. 대부분은 function 키워드 바로 뒤에 붙인다. ex) function*

// 선언식
function* genDecFunc() { 
	yield 1; 
}

// 표현식
const genExpFunc = function* () { /* ... */ }

// 객체 메서드
const obj = {
	* genObjMethod() { /* ... */ }
}

// 클래스 메서드
class MyClass {
	* genClsMethod() { /* ... */ }
}

❗️ 제너레이터 함수는 화살표 함수로 정의할 수 없고, new 연산자를 사용하는 생성자 함수로 호출할 수 없다.

const genArrowFunc = * () => { /* ... */ } // Error! Unexpected token '*'

function* genFunc() { /* ... */ }
new genFunc(); // Error! genFunc is not a constructor

제너레이터 함수 자체는 이터러블이므로 아래처럼 전개문법을 사용할 수도 있다.

function* generateSequence() {
	yield 1;
	yield 2;
	yield 3;
}
const res = [0, ...generateSequence()] // [0, 1, 2, 3]

console.log(Symbol.iterator in generateSequence.prototype) // true
// 제너레이터 함수는 Symbol.iterator 메서드를 상속받으므로 이터러블이다

제너레이터 함수는  메서드를 상속받으므로 이터러블이다

제너레이터 함수는 Symbol.iterator 메서드를 상속받으므로 이터러블이다

제너레이터 객체


<aside> 💡 제너레이터 객체는 이터러블(iterable)이면서 이터레이터(iterator)다.

</aside>