제너레이터와 실행컨텍스트

Sming·2022년 10월 6일
8

제너레이터를 공부하면서 생긴 의문이다. 과연 제너레이터 함수는 실행 컨텍스트에서 어떻게 돌아가는 걸까?

https://tc39.es/ecma262/#sec-generator-function-definitions

자바스크립트에서의 일반 함수가 실행 컨텍스트에서 돌아가는 순서는 다음과 같다.

  • 함수가 호출될시 실행컨텍스트의 콜스택에 함수가 쌓이게 된다.
  • 생성된 실행컨텍스트 내부의 환경레코드의 [[outerEnv]] 슬롯이 자신의 상위 스코프를 가르킨다.([[Environment]]에서 받아옴)
  • 함수의 실행을 마칠시에 실행컨텍스트에서 제거된다.

하지만 제너레이터 함수의 경우 어떻게 next를 통해서 중단된 시점부터 다시 시작하고 value를 기억하는 것일까?

그런데 함수의 실행이 끝나고도 함수내부의 value를 기억한다? -> 이것은 클로저와 유사하게 동작하겠구나라고 생각하였다.

function* myGenerator() {
  yield '1';
}

var gen = myGenerator();

const result1 = gen.next();
// result1 = {value = '1'; done = false}
const result2 = gen.next();
// result3 = {value = undefined; done = true}

예상과 비슷하게 클로저처럼 gen 변수가 generator의 실행컨텍스트를 참조하여 가비지 컬렉터가 제거할 수 없도록 설정하는것 같았다.

실행컨텍스트에서 generator가 실행되는 과정은 다음과 같다.

  1. 전역 객체가 평가되면서 전역 실행컨텍스트가 콜스택에 쌓이게 된다.

  1. myGenerator가 실행되면서 콜스택에 쌓이게 된다. 이때 환경레코드의 [[outerEnv]] 내부 슬롯은 전역 환경 레코드를 가르키게 된다.

  1. myGenerator는 실행을 마쳤기에 실행컨텍스트의 콜스택에서 빠져나오게 된다. 하지만 gen 변수가 myGenerator를 참조하고 있기에 메모리에서 없어지지 않고 남아있게 된다.

  1. gen.next()를 통해서 myGenerator를 실행한다. 메모리상에 존재하는 myGenerator의 실행컨텍스트를 다시 콜스택으로 옮기게 된다. 그렇게 다시 myGenerator를 실행할 수 있다.

  1. yield를 만나게 되면 다시 myGenerator의 실행을 멈추고 {value: ..., done: false}를 내보내게 된다. myGenerator의 실행을 멈추었기 때문에 다시 실행컨텍스트의 콜스택에서 빠져나오게 된다.

  1. 마지막으로 generator의 실행이 완전히 종료했을때다. 마지막 yield에서 {value: ..., done: true}를 받았다면 generator는 실행을 멈추게 된다. done: true를 받을시에는 실행을 멈추고 남아있는것이 아니라 완전히 메모리에서 제거되게 된다.

지금까지 제너레이터가 실행컨텍스트에서 어떻게 동작했는지 알아보았다. 함수에서 값을 기억하고 있다는 점에서 클로저와 유사하게 동작을 하고 있는것 같았다.

profile
딩구르르

0개의 댓글