해결된 질문
작성
·
211
0
원래 LE가 함수호출시 만들어지는것으로 이해를했는데 클로저에서 혼란을 겪었습니다.
그래서 위 내용을 찾아보았습니다. 함수객체에서 인터널슬롯으로 [[Environment]] 프로퍼티를 보았습니다.
함수 선언 당시의 outerEnvironmentReference 를 함수객체에 저장하는건가요?
그리고 나중에 함수 호출할 시 생성되는 EC의 LE에 초기화 시켜주나요?
영어 실력이부족해서 해당 초기화 내용은 찾지 못했습니다..
답변 2
1
다음과 같이 외부함수 A에서 내부함수 B를 선언하고, B를 return한 경우를 가정해 봅시다.
1 | function A () {
2 | var a = 1;
3 | var b = 2;
4 | function B () { return ++a; }
5 | return B;
6 | }
7 | var getA = A();
8 | console.log(getA()); // 2
나머지 내용은 생략하고, 함수 선언 및 호출과 EC에만 포커스를 맞춰서
자바스크립트 엔진의 처리과정을 순서대로 따라가 볼까요? (괄호는 줄번호)
1. A함수 선언 (1)
2. A함수 호출 (7) > A의 E.C 생성
3. B함수 선언 (4)
4. A함수 실행종료 (6) > A의 E.C 제거됨. "A의 L.E는 소멸될까?"
5. B함수 호출 (8) > B의 E.C 생성
5.에서 B의 E.C가 생성될 때, 해당 E.C에는 outerEnvironmentReference(O.E라 합시다)가 담기는데,
이 O.E는 곧 A의 L.E입니다.
-----------------------------------------------------------
"A는 이미 실행 종료된 시점인데 어떻게 A의 L.E가 살아있지?
B의 E.C는 B가 호출될 때 생성된다고 했는데,
혹시 O.E는 예외적으로 B가 선언될 때에 주입되는거 아닐까?"
-----------------------------------------------------------
라는 의심이 들 수 있는데, 엔진에서의 구동방식은 다음과 같습니다.
A의 E.C는 A의 실행이 종료되는 시점에 제거되지만,
이 때 만약 A의 내부에서 선언한 변수가 재사용될 가능성이 있는 경우,
자신의 L.E는 소멸시키지 않고 남겨둡니다(the L.E that the function was closed over).
따라서 B의 E.C가 생성되는 시점(when evaluating the code of the function)에
B의 O.E, 즉 A의 L.E가 정상적으로 활용(used as the outer environment)될 수 있는 것입니다.
그러니까 B의 O.E는 B가 아닌 A의 시선에서 접근하면 이해가 되실거에요.
최신 브라우저에서는 A의 L.E를 모두 남겨두진 않고,
'실제로 미래에 호출할 것으로 예상되는 변수들'만 남기는 식으로 최적화가 이루어져 있습니다.
코드상에서는 b변수는 불필요하므로 제거되고 a만 남겠죠.
다만 이런 내용을 명세서에서 확인할 수는 없습니다.
0