[JS] 제너레이터

mj·2021년 6월 11일
0
post-custom-banner

제너레이터(generator)란?

함수의 실행 중 멈췄다가 다시 재개할 수 있는 독특한 기능이다.
C언어의 포인터처럼 함수에 *을 붙여서 선언한다.

function* generatorFunc(){
}

실행을 멈추면서 값을 하나씩 꺼내서 전달할 수 있다.
제너레이터는 일반 함수와 달리 함수를 호출하면 제너레이터 객체를 반환한다.

function* generatorFunc(){
}

const generator = generatorFunc(); //[object Generator] 생성

제너레이터는 값을 미리 만들어 놓지 않고 필요한 순간에 값을 계산하여 전달하기 때문에 메모리 측면에서 효율적이다.
제너레이터가 실행을 멈추는 것은 yield 키워드를 통해서 할 수 있다

function* generatorFunc(){
  yield 10;
  yield 20;
  return 'finished'
}
const generator = generatorFunc(); //[object Generator] 생성

우리가 yield를 만나기 전에는 코드를 멈추게 된다. 따라서 10이라는 value를 yield를 통해 전달하려면 제너레이터 객체의 next()라는 메소드를 사용해야 한다.

function* generatorFunc(){
  yield 10;
  yield 20;
  return 'finished'
}
const generator = generatorFunc(); //[object Generator] 생성
const nextgen = generator.next(); // {value : 10, done: false}

우리가 next() 메소드를 사용하면 제너레이터 객체의 가장 가까운 yield <value>를 만날 때 까지 실행한다. 함수의 프로퍼티 중 done은 함수의 코드가 종료되었을 때 true를 반환하기 때문에 아직 모든 yield를 실행하지 않았음으로 false인 상태다.

function* generatorFunc(){
  yield 10;
  yield 20;
  return 'finished'
}
const generator = generatorFunc(); //[object Generator] 생성
const nextgen1 = generator.next(); // {value : 10, done: false}
const nextgen1 = generator.next(); // {value : 20, done: false}
const nextgen1 = generator.next(); // {value : 'finished', done: true}

next() 메서드를 통해 함수가 종료되는 시점인 return에 다다르면 value가 return 값으로 변하고 done의 값이 true로 변한다.

또한, 제너레이터는 iterable 객체이다.

//배열도 next()메소드를 가지고 있고 value와 done이라는 프로퍼티를 지니고 있다.
const arr = [10, 20, 30];
const iter = arr[Symbol.iterator]();
console.log(iter.next()); // {value: 10, done: false}
function* generatorFunc(){
  yield 10;
  yield 20;
  yield 30;
}

for (const c of generatorFunc()){
	console.log(v); //done이 true가 될 때까지 next()를 실행하며 반복.
}

const arr = [...generatorFunc()]; // 전개연산자도 next()를 통해 done이 참이 될 때까지 반복한다.
console.log(arr); //[10, 20, 30]

제너레이터 함수끼리 호출할 때는
yield키워드에 *을 붙여서 호출한다

yield* generatorFunc();

그리고 제너레이터는 외부로부터 데이터를 받아서 소비할 수도 있다.

function* generatorFunc(){
  const data1 = yield;
  console.log(data1);
  const data2 = yield;
  console.log(data2);
  
}
const generator = generatorFunc(); //[object Generator] 생성
const nextgen1 = generator.next(10) //next()메소드의 인수로 값을 전달하여 할당하였다.

그래서 제너레이터를 어디에 쓰는데?

제너레이터는 보았다싶이 다른 함수와 협업 멀티태스킹을 할 수 있다.

//제너레이터 함수 선언
function* minsu(){
	const myMsgList = [
      '안녕 나는 민수야',
      '만나서 반가워',
      '내일 영화 볼래?',
      '시간 안 되니?',
      '내일 모레는 어때?'
    ];
  for (const msg of myMsgList){
  	console.log('수지: ', yield msg);
  }
}
function suji() {
  const myMsgList = ['', '안녕 나는 수지야', '그래 반가워', '...'];
  const gen = minsu();
  for (const msg of myMsgList){
  	console.log('민수: ', gen.next(msg).value);
  }
}
suji();
/* 실행결과
민수 : 안녕 나는 민수야
수지 : 안녕 나는 수지야
민수 : 만나서 반가워
수지 : 그래 반가워
민수 : 내일 영화볼래?
수지 : ...
민수 : '시간 안되니?'
*/
  1. 제너레이터의 next메소드를 사용하면 먼저 수지의 대답을 yield를 통해 반환한다. // 빈 문자열 ''
  2. 수지의 대답 후 다시 제너레이터가 중지되고 민수의 대답을 듣는다. //index의 1번부터.
  3. 반복.

제너레이터를 통해 다른 함수와 멀티태스킹을 할 수 있다는 것을 알게 되었다.
참고 : 실전 리액트 프로그래밍

post-custom-banner

0개의 댓글