교재/코어 자바스크립트

코어 자바스크립트 | 챕터 2: 실행 컨텍스트

피까츄 2025. 4. 22. 00:38

<실행 컨텍스트란?> 
실행 컨텍스트(Execution Context)
실행할 코드에 제공할 환경 정보들을 모아놓은 객체

스택(FIFO)
큐(LIFO)

코드를 실행할 때 환경 정보를 모아 컨텍스트를 구성,
이를 콜 스택에 쌓아올렸다가
가장 위에 있는 컨텍스트와 관련있는 코드를 실행한다

흔한 예제(함수 실행)

inner
outer
전역 컨텍스트 순으로 쌓여서
위에서부터 빠져나간다

VariableEnvironment: 현재 컨텍스트 내의 식별자들에 대한 정보+ 외부 환경 정보, 변경사항이 반영되지 않는 LexicalEnvironment

LexicalEnvironment: 변경사항이 실시간으로 반영되는 VariableEnvironment

ThisBinding: this 식별자가 바라봐야 할 대상 객체


<VariableEnvironment>
LexicalEnvironment와 같은 내용을 담지만 최초 실행 시의 스냅샷을 유지한다.

먼저 여기에 담고 LexicalEnvironment를 만들어서 후자를 주로 사용

~VariableEnvironment LexicalEnvironment의 내부는 environmentRecord와 outer-EnvironmentReference로 구성돼 있습니다. 초기화 과정 중에는 사실상 완전히 동일하고 이후 코드 진행에 따라 서로 달라지게 됩니다~


<LexicalEnvironment>
컨텍스트를 구성하는 환경 정보들을 사전에서 접하는 느낌으로 모아놓은 것

environmentRecord와 호이스팅
environmentRecord에는 현재 컨텍스트와 관련된 코드의 식별자 정보들이 저장된다(매개변수 이름, 함수 선언, 변수명)
컨텍스트 내부 전체를 처음부터 끝까지 훑으며 순서대로 수집합니다.

이로 인해 코드가 실행되기 전에도 자바스크립트 엔진은 이미 해당 환경의 변수명을 모두 알게된다
호이스팅(자바스크립트 엔진이 식별자들을 맨 위로 끌어올린 것과 같다는 의미)

변수는 선언부와 할당부를 나누어 선언부만 끌어올리는 반면 함수 선언은 함수 전체를 끌어올립니다

 function a () {
            console.log(b);
            var b = 'bbb';
            console.log(b);
            function b() {}
            console.log(b);
        }

        a();

을 호이스팅 된 상태로 바꾼다면


        function a() {
            var b;
            function b() { }

            console.log(b);
            b = 'bbb';
            console.log(b);
            console.log(b);
        }
        a();
가 된다

함수 선언문(function declaration)
: function 정의부만 존재하고 별도의 할당 명령이 없는 것, 반드시 함수명이 정의돼 있어야한다
함수 선언문은 전체를 호이스팅한다

function sum (a,b) {
return a+b;
}


함수 표현식(function expression)
: function을 별도의 변수에 하당하는 것
(익명 함수 표현식)
변수 선언부만 호이스팅이다

~함수도 하나의 값으로 취급할 수 있다는 것이 바로 이런 것, 함수를 다른 변수에 값으로써 '할당'한 것이 곧 함수 표현식이다~

var multiply = function (a,b) {
return a*b;
}


//기명 함수 표현식
var c = function d() { /* ... */}
c();
d();//에러

//

기명 함수 표현식은 외부에서 함수명으로 함수를 호출할 수 없고, 함수 내부에서만 접근할 수 있다

전역 컨텍스트가 활성화될 때 전역 공간에 선언된 함수들이 모두 가장 위로 끌어올려지는데, 동일한 변수명에 서로 다른 값을 할당할 경우 나중에 할당한 값이 먼저 할당한 값을 덮어씌웁니다.

상대적으로 함수 표현식이 안전하다!



스코프(scope) 식별자에 대한 유효범위
외부에서 선언한 변수는 내부에서도 접근 가능하지만,
내부에서 선언한 변수는 외부에서는 접근 불가능하다

특이하게 자바스크립트는 전역 공간을 제외하면
오직 함수에 의해서만 스코프가 생성된다

식별자의 유효범위를 안-> 밖으로 차례로 검색해나가는 걸
스코프 체인이라고 한다
이를 가능케하는 것이 outerEnvironmentReference이다


스코프 체인
outerEnvironmentReference는 호출 함수가 선언될 당시의 LexicalEnvironment를 참조한다
>>선언될 당시의<<

ex) A함수 내부에 B함수 선언, B함수 내부에 C함수 선언

함수 C의 outerEnvironmentReference는 B의 LexicalEnvironment 참조

함수 B의 LexicalEnvironment에 있는outerEnvironmentReference는 함수가 선언되는 A의  LexicalEnvironment 참조

마지막엔 전역 컨텍스트의  LexicalEnvironment가 있을 것

스코프 체인 상에서 가장 먼저 발견된 식별자에만 접근 가능하게 된다

var a = 1;
        var outer = function () {
                var inner = function() {
                    console.log(a);
                    var a = 3;
                };
                inner();
                console.log(a);
        };
        outer();
        console.log(a);

### 부가 설명 ###
🎯 정리하면

용어 의미 비유
Lexical Environment 실행 컨텍스트의 환경 전체 "내 방"
environmentRecord 현재 스코프에 선언된 변수/함수 목록 "내 책상 위 메모"
outerEnvironmentReference 바깥 환경을 참조하는 연결 고리 "바깥 방으로 통하는 문"

🔄 예시로 다시 볼게요
var a = 1;

function outer() {
  var b = 2;
  function inner() {
    var c = 3;
    console.log(a, b, c);
  }
  inner();
}
outer();
각 함수가 실행될 때 컨텍스트가 만들어지고 다음이 저장돼요:

✅ inner의 실행 컨텍스트
Lexical Environment

environmentRecord → { c: 3 }

outerEnvironmentReference → outer의 Lexical Environment

✅ outer의 실행 컨텍스트
Lexical Environment

environmentRecord → { b: 2, inner: function }

outerEnvironmentReference → 전역 Lexical Environment

✅ 전역 컨텍스트
Lexical Environment

environmentRecord → { a: 1, outer: function }

기억하시면 좋은 것!
environmentRecord는 내 스코프의 정보

outerEnvironmentReference는 바깥 스코프를 찾는 연결 고리

이 둘이 합쳐져서 Lexical Environment가 된다

전역변수: a, outer
지역변수: outer 함수 내부에서 선언한 inner와 inner 함수 내부에서 선언한 a
함수 내부에서 선언한 변수는 무조건 지역변수이다.


<this>
실행 컨텍스트의 thisBinding에는 this로 지정된 객체가 저장됨
지정되지 않은 경우 this에는 전역 객체가 저장됨


<정리>

실행 컨텍스트: 환경 정보들을 모아놓은 객체
전역 컨텍스트와 함수 실행에 의한 컨텍스트가 있다
실행 컨텍스트 객체는 활성화되는 시점에 VariableEnvironment, LexicalEnviroment, ThisBinding 세 가지 정보를 수집

VariableEnvironment, LexicalEnviroment은 동일한 내용 구성
하지만 LexicalEnviroment은 변경 사항이 즉시 반영, VariableEnvironment는 초기 상태를 유지

VariableEnvironment, LexicalEnviroment는
environmentReference: 매개변수명, 변수 식별자, 선언 함수의 함수명
outerEnvironmentReference: 직전 컨텍스트의 정보를 참조

호이스팅: environmentReference이 수집 과정을 추상화 한 것. 끌어올린다는 표현을 사용
함수 선언문과 함수 표현식의 차이가 생긴다(표현식은 선언부만을 호이스팅, 선언문은 전체를 호이스팅)

스코프: 변수의 유효범위
outerEnvironmentReference는 해당 함수가 선언된 위치의 LexicalEnvironment를 참조
변수에 접근하려하면 현재 컨텍스트의 LexicalEnvironment를 탐색해서 발견되면 반환, 발견하지 못할 경우 outerEnvironmentRecord에 담긴 LexicalEnvironment를 탐색
전역의 LexicalEnvorionment까지 탐색했는데도 변수를 찾지 못하면 undefined 반환

전역 컨텍스트의 LexicalEnviornment에 담긴 변수를 전역 변수라 한다

this는 실행 컨텍스트를 활성화 하는 당시에 지정된 this가 저장된다
함수 호출 방법에 따라 값이 다른데, 지정되지 않았으면 전역 객체가 저장된다.