이 글은 프론트엔드 개발을 1년정도 해본 예비 주니어 개발자가 코어 자바스크립트를 읽고 쓴 글로, 잘못된 것이나 수정할 부분이 있다면 댓글로 알려주세요.
실행 컨텍스트는 실행할 코드에 제공할 환경 정보들을 모아놓은 객체라고 합니다.
동일 환경에 있는 코드들을 실행할 때, 필요한 환경 정보들을 모아 컨텍스트를 구성하고, 이걸 콜 스택에 쌓았다가 가장 위에 쌓인 커텍스트와 관련된 코드를 실행하는 식으로 전체 코드의 순서를 정한다고 합니다.
여기서 실행 컨텍스트를 생성하는 녀석은 함수, es6의 {}(블락), 그리고 eval() 함수가 있습니다.
기본적으로 eval() 함수는 지양하므로 저희가 자주 쓰는건 함수를 실행하는 것입니다.
그리고 우리가 아무것도 하지 않아도 js를 실행하면 전역 컨텍스트가 생성됩니다.
실행 컨텍스트는 안의 코드를 실행하기 위한 데이터들을 실행 컨텍스트 객체 안에 저장합니다.
물론 개발자가 코드로 확인은 불가능하고 엔진 활용을 위해서만 저장됩니다. 담기는 정보는 다음과 같습니다.
LexicalEnviroment: 현재 컨텍스트 내부의 식별자들에 대한 정보와 외부 환경 정보들입니다.
VariableEnvironment: 현재 컨텍스트 내부의 식별자들에 대한 정보와 외부 환경 정보 선언 시점의 LexicalEnvironment의 캡쳐본입니다. 변경사항은 적용되지 않습니다.
ThisBinding: this 식별자가 바라보는 대상 객체입니다.
초기에 실행될 때, LexicalEnvironment와 데이터가 같지만, 변경사항이 있어도 그대로 유지됩니다.
실행컨텍스트 생성 시에, VariableEnvironment를 먼저 만들고 LexicalEnvironment에 그대로 복사합니다.
이것 내부에는 2가지 녀석이 있습니다.
이 녀석은 현재 컨텍스트와 관련된 코드들의 식별자 정보들이 저장됩니다.
컨텍스트를 구성하는 함수에 지정된 매개변수 식별자, 선언된 함수, var로 선언된 변수명들이 담깁니다.
컨텍스트 내부 전체를 처음부터 끝까지 쭉 훑어서 순서대로 수집합니다.
코드를 실행하기 전에, 식별자들의 데이터를 모두 알고 있는 것입니다. 그렇다면 우리가 평소에 알고 있는 호이스팅 이라는 개념에 적용할 수 있습니다. 엔진이 이미 식별자들을 알고 있다는 것을 생각해보면 변수 선언과 함수 선언식으로 만든 함수들은 위로 끌어올려진다고 생각해도 됩니다.
이런 호이스팅을 예제로 알아봅시다.
function a() {
console.log(test); // undefined
var test; // 선언식이 위로 끌어올려진다.
console.log(test); // undefined
var test = 10; // 선언식은 끌어올려진다 하지만 초기화는 안된다.
console.log(test); // 10
}
function b(){
console.log(testFunc);// function testFunc(){}
function testFunc(){} // var testFunc = function(){} 로 호이스팅 된다.
console.log(testFunc);// function testFunc(){}
}
우선 이걸 설명하기 전에 스코프에 대해서 말해보겠습니다. 스코프는 식별자(변수, 함수)의 유효범휘입니다.
개인적인 생각으로는 실행 컨텍스트의 범위라고 생각합니다(정확X)
내부 스코프에서는 외부 스코프에 있는 식별자에 접근할 수 있습니다. 하지만 외부에서 내부는 안됩니다.
내부에서 어떤 식별자를 찾을 때, 가장 안에 있는 스코프에서 밖으로 차례대로 찾는걸 스코프 체인이라고 합니다.
그리고 이걸 가능하게 하는 것은 outerEnvironmentReference입니다.
outerEnvironmentReference는 현재 함수가 선언될 당시에 그 함수를 실행한 함수의LexicalEnvironment를 참조합니다.
var test = 1;
function outer(){
// environmentRecord: { test, inner }
//outerEnvironmentReference: { GLOBAL, { test, outer }}
function inner(){
// environmentRecord: { test }
// outerEnvironmentReference: { outer, { inner }}
console.log(test)// undefined -> inner
var test = 2;
}
inner();
console.log(test); // 1 -> outer -> GLOBAL
};
outer();
console.log(test); // 1 -> GLOBAL
실행 컨텍스트는 위와 같이 복잡한 방법으로 실행된다. 이런것들을 알고 개발하도록 하자