[ES6] Generator

sangminnn·2020년 4월 15일
0

글로 정리하는 ES6

목록 보기
11/11

개념

먼저 Generator 란 직역해보자면 생성기 라는 의미를 가지는데

실제 역할은 이터러블을 생성하는 함수 이다.

이번에는 매우 생소한 개념이기 때문에 예제 코드부터 보고 가보자.

function* threeStep() {
	console.log('one step');
  	yield 1;
  	console.log('two step');
  	yield 2;
  	console.log('three step. The End!');
}

// 함수 표현식으로도 가능!

let threeStep = function* () {
	// Something ...
}

위의 함수가 기본적으로 Generator 함수를 만드는 방식이다.

여기서 기존의 함수와 다른 부분을 찾아보자면

*yield 를 찾을 수 있겠다.

그렇다면 이들은 어떤 역할을 하는 것일까?

먼저 * 는 function 뒤에 붙어 이 함수가 Generator 함수라는 것을 인지시켜주는 식별자 역할을 하는 것이고

yield 는 마치 함수에 return point를 두어 단계별로 return 할 수 있도록 해주는 키워드 이다.

단계별 return 동작 에 대해 알아보기 전에 한가지만 더 짚어보고 넘어가야할 것이 있는데

Generator 함수의 내부가 어떻게 구성되어있는지 를 알아봐야 동작에 대해 알 수 있다.

위의 그림을 보면 threeStep Generator 함수의 prototype에 메서드들이 정의되어 있는데

next, return, throw 이 3가지를 확인할 수 있다.

여기서 next 메소드는 위에서 언급한 단계별 동작 에 대한 역할을 하고

return, throw단계별 동작의 정지 에 대한 역할을 한다.

++)추가적으로 Generator 함수의 return type은 object 라는 점도 눈여겨볼 특징 중 하나이다.

const ts = threeStep();

typeof ts // object

Generator 함수의 동작

이제 동작에 대한 코드를 한번 보자.


// const ts = threeStep();

ts.next(); 
// one step
// { value: 1, done: false }
ts.next();
// two step
// { value: 2, done: false }
ts.next();
// three step. The End!
// { value: undefined, done: true }

위의 코드를 참고하여 동작에 대해 이해를 해보자면

먼저, Generator 함수를 선언할 당시에 yield 라는 Return Check Point 를 만들어 두고

Check Point 까지의 동작을 next 메소드로 접근하는 것이다.

보다시피 next 메소드의 return 값으로는 yield point 에 존재하는 값(value)과

순회 동작의 종료여부를 알려주는 done 이 return 되는 것을 알 수 있다.

여기서 yield 동작에 대한 value 값 결정 규칙에 대해 보다 더 자세히 알아보겠다.

function* calc(prev, post) {
  let result = 0;
  console.log(`Initial result: ${result}`);
  console.log(result)
  result = yield prev + post;
  console.log(result)
  console.log('point 1', result)
  console.log(`Middle result: ${result}`);
  console.log('point 2', result);
  console.log(result)
  result = yield;
  console.log(result)
  console.log('point 3', result);
  console.log(`Last result: ${result}`);
}

위와 같은 코드를 통해 세세하게 포인트를 잡아준 다음 next를 실행해 보았다.

먼저 Generator 함수 선언 후에 변수에 값을 할당한 이후 next 동작별로 보자.

1. 첫번째 next

result 값은 0으로 선언되어 시작했기 때문에 Initial result와 result 값은 0이 출력

value 값은 yield 뒤에 연산자에 따라 8 이 출력된다.

2. 두번째 next

이번에는 result에 대한 별도 지정이 없기 때문에 yield 전까지는 모두 undefined

그리고 value 값은 yield 뒤에 연산자가 없기 때문에 undefined 로 출력된다.

3. 세번째 next

이 부분이 가장 중요한 부분인데

next에서 인자에 값을 넣어주었을 때 를 볼 수 있다.

여기서는 이제 연산자가 존재하지 않기 때문에, 인자 값이 return 값 으로 나타나

next 메소드의 파라미터로 넘겨진 2가 result 변수에 할당 된다.

더이상 yield 키워드가 없으므로 done은 true가 된다.


return, throw 메소드

위에서 next 메소드에 대해 알아보았기 때문에 나머지 메소드도 알아보자.

먼저 return 메소드에 대해 알아보자.

function* infiniteNum() {
    let value = 0;
  	while(true) {
      yield ++value
    }
};

let exam = infiniteNum();
console.log(exam.next()); // { value: 1, done: false }
console.log(exam.next()); // { value: 2, done: false }
console.log(exam.next()); // { value: 3, done: false }
console.log(exam.return(50)); // { value: 50, done: true }

위의 코드에서 보는 것과 같이 계속되는 동작에서 중단하고자 할 때

return 메소드를 사용해주면 done이 true가 되어 더이상 동작하지 않게된다.

function* infiniteNum() {
    let value = 0;
  	try {
      while(true) {
        yield ++value;
      }
    } catch (e) {
		console.log(e);
    }
};

let exam = infiniteNum();
console.log(exam.next()); // { value: 1, done: false }
console.log(exam.next()); // { value: 2, done: false }
console.log(exam.next()); // { value: 3, done: false }
console.log(exam.throw("Error!!!"));
// Error!!!
// { value: undefined, done: true }

throw 메소드는 위의 코드에서 보는 것과 같이

try-catch 구문에서 파라미터로 넘겨준 Error Message를 출력해주고

반복 동작을 종료시켜주는 역할을 한다.

마치며 ...

오늘 글도 Jbee 님의

https://jaeyeophan.github.io/2017/04/22/ES6-10-Generator/

와 poiemaweb 의

https://poiemaweb.com/es6-generator

글을 공부하며 정리한 내용입니다.

profile
생각하며 코딩하려고 노력하는 개발자가 되겠습니다.

0개의 댓글