실행할 코드에 제공할 환경 정보들을 모아놓은 객체이다.
동일한 환경에 있는 코드들을 실행할 때 필요한 환경 정보들을 모아 컨텍스트를 구성하고, 이를 콜스택에 쌓아 올렸다가 가장 위에있는 컨텍스트와 관련 있는 코드들을 실행하는 식으로 전체 코드의 환경과 순서를 보장한다.
- 컨텍스트를 구성하는 방법으로는 전역공간, eval() 함수, 함수 실행 등이 있다.
스택과 큐는 데이터 구조의 종류이다.
스택의 구조는 우물같은 구조라고 하였다. 때문에 이 구조를 잘 생각해보면 한 실행 컨텍스트가 콜 스택의 맨 위에 쌓이는 순간이 곧 현재 실행할 코드에 관여하게 되는 시점임을 알 수 있다. 기존 컨텍스트가 새로 쌓인 컨텍스트보다 아래에 위치할 수 밖에 없기 때문이다.
활성화된 실행 컨텍스트의 수집 정보는 다음과 같다.
VariableEnvironment는 LexicalEnvironment와 같지만 최초 실행 시 스냅샷을 유지한다는 점이 다르다. 실행 컨텍스트를 생성할 때 VariableEnvironment에 정보를 먼저 담은 다음 그대로 복사해서 LexicalEnvironment를 만들고 이후에는 LexicalEnvironment를 주로 활용하게 된다.
VariableEnvironment와 LexicalEnvironment 내부는 environmentRecord와 outer-EnvironmentReference로 구성되어 있다.
코드가 실행되기 전임에도 불구하고 자바스크립트 엔진은 이미 해당 환경에 속한 코드의 변수명을 모두 알고 있게 되는 셈.
자바스크립트 엔진은 식별자들을 최상단으로 끌어올려놓은 다음 실제 코드를 실행한다. 여기서 호이스팅 개념이 등장!
코드 해석을 좀 더 수월하게 하기 위해 environmentRecord의 수집 과정을 추상화한 개념으로, 실행 컨텍스트가 관여하는 코드 집단의 최상단으로 이들을 '끌어올린다'고 해석하는 것이다.
변수는 선언부와 할당부를 나누어 선언부를 끌어올리고, 함수 선언은 전체를 끌어올린다. 이 때 함수선언문과 함수 표현식으로 나뉜다.
함수 선언문은 function 정의로 바로 함수를 선언하는 것이고 함수 표현식은 정의한 function을 별도의 변수에 할당하는 것을 말한다.
function a () { /*...*/ } // 함수 선언식
var b = function () { /*...*/ } // 함수 표현식. 변수명 b가 곧 함수명
var c = function d() { /*...*/ } // 기명 함수 표현식. 변수명 c, 함수명 d.
함수 선언문과 함수 표현식은 실무에서 발생할 수 있는 에러에서 디버깅 시에 큰 차이가 발생한다.
함수 선언식으로 함수를 작성하게 되면 전역 컨텍스트가 활성화 될 때 전역 공간에 선언된 함수들이 모두 가장 위로 끌어올려지고, 동일한 변수명에 서로 다른 값을 할당할 경우 나중에 할당한 값이 먼저 할당한 값을 덮어 씌우게 된다. 때문에 예를들어 5000줄의 코드가 있다고 가정하고 두 사람이 같은 파일에서 작업을 할 때 A, B 두 사람이 같은 파일 안에서 같은 이름의 함수를 함수선언식으로 만들 경우 실제로 호출되는 함수는 마지막에 선언된 함수 뿐이다.
스코프(Scope)란 식별자에 대한 유효범위이다. 스코프 체인이란 식별자의 유효범위를 안에서부터 바깥으로 차례로 검색해나가는 것이다. 그리고 이를 가능하게 하는 것이 바로 outerEnvironmentReference이다.
outerEnvironmentReference는 자신이 선언된 시점의 LexicalEnvironment만 참조하는 연결 리스트 형태를 띄는 구조적인 특성상 여러 스코프에 동일한 식별자를 선언한 경우 무조건 스코프 체인 상에서 가장 먼저 발견된 식별자에만 접근 가능하다.
내부 함수에서 전역변수와 같은 이름의 변수를 선언하게 될 경우, 전역 공간에서 선언한 동일한 이름의 변수에는 접근이 불가능하다. 이를 변수 은닉화라고 한다.
//예시
var a = 1;
var outer -= function () {
var inner = function () {
console.log(a); //undefined
var a = 3;
};
inner()'
console.log(a);
};
outer();
console.log(a);
전역변수와 지역변수
전역 컨텍스트의 LexicalEnvironment에 담긴 변수를 전역변수이고, 함수 내부에서 선언한 변수는 무조건 지역변수이다. 안전한 코드 구성을 위해 가급적 전역변수의 사용은 최소화하는 것이 좋다.
읽어보면 좋을 글: [번역] 자바스크립트 스코프와 클로저(JavaScript Scope and Closures)
this 식별자가 바라봐야 할 대상 객체.(챕터 3에서 자세히 다룸).
실행 컨텍스트를 활성화하는 당시에 지정된 this가 저장. 함수를 호출하는 방법에 따라 그 값이 달라지는데, 지정되지 않은 경우에는 전역 객체가 저장된다.