출저
- 코어자바스크립트 - 정재남
실행 컨텍스트 (execution context) 는 실행할 코드에 제공할 환경 정보들을 모아놓은 객체
동일한 환경에 있는 코드들을 실행할 때 필요한 환경 정보들을 모아 컨텍스트를 구성하고, 이를 콜 스택에 쌓아올렸다가, 가장 위에 쌓여있는 컨텍스트와 관련 있는 코드들을 실행하는 식으로 전체 코드의 환경과 순서를 보장한다.
동일한 환경이란 하나의 실행 컨텍스트를 구성할 수 있는 방법으로 전역공간, eval()함수, 함수 등이 있다. 보통 함수를 실행할 때 실행 컨텍스트를 구성한다고 생각하면 된다.
// ------------------------------- (1)
let a = 1;
function outer() {
function inner() {
console.log(a);
let a = 3;
}
inner(); // ------------------ (2)
console.log(a);
}
outer(); // ---------------------- (3)
console.log(a);
현재 컨텍스트 내의 식별자들에 대한 정보 + 외부 환경 정보. 선언 시점의 LexicalEnvironment의 스냅샷으로, 변경 사항은 반영되지 않음.
environmentRecord + outer-EnvironmentReference
실행 컨텍스트를 생성할 때 VariableEnvironment에 정보를 먼저 담은 다음, 이를 그대로 복사해서 LexicalEnvironment를 만들고, 이후에는 LexicalEnvironment 를 주로 활용한다.
현재 컨텍스트와 관련된 코드의 식별자 정보들
이 저장된다. 컨텍스트 내부 전체를 처음부터 끝까지 쭉 훑어나가며 순서대로 수집한다.
예를 들어, 함수자체, let, const로 선언된 변수의 식별자 등 을 수집하는데 이는 실행되기 전의 상태이고 자바스크립트 엔진이 이미 해당 환경에 속한 코드의 변수명들을 모두 알고 있게 되는 셈이다. 이렇게 식별자들을 최상단으로 끌어올려놓은 다음 실제 코드를 실행한다 라는 호이스팅
이라는 개념과 동일하다고 봐도 무관하다.
function a (x) {
console.log(x);
let x;
console.log(x);
let x = 2;
console.log(x);
}
a(1)
인자를 함수 내부의 다른 코드보다 먼저 선언 및 할당이 이뤄진 것으로 간주 할 수 있다.
function a () {
let x =1; // 수집 대상 1 (매개변수 선언)
console.log(x); // (1)
let x; // 수집 대상 2 (변수 선언)
console.log(x); // (2)
let x = 2; // 수집 대상 3 (변수 선언)
console.log(x); // (3)
}
a()
호이스팅 처리를 보기 쉽게 나열해 보기.
function a () {
let x; //수집 대상 1의 변수 선언 부분
let x; //수집 대상 2의 변수 선언 부분
let x; //수집 대상 3의 변수 선언 부분
x =1; //수집 대상 1의 할당 부분
console.log(x); // (1)
console.log(x); // (2)
let x = 2; //수집 대상 3의 할당 부분
console.log(x); // (3)
}
a(1)
// (1), (2) 모두 1이 출력, (3) 에서는 2 가 출력
function a () { } // a 가 함수명 이자 변수명
a()
let b = function () { } // 익명 함수 표현식, b 가 함수명 이자 변수명
b()
let c = function d () { } // 기명 함수 표현식, 변수명은 c, 함수명은 d
c() // 실행 됨
d() // 실행 안됨 error
console.log(sum(1, 2));
console.log(multiply(3, 4));
function sum (a, b) { // 함수 선언문 sum
return a + b;
}
let multiply = function (a, b) { // 함수 표현식 multiply
return a * b;
}
함수 선언문과 함수 표현식, 호이스팅을 마친 상태
function sum (a, b) { // 함수 선언문은 전체를 호이스팅
return a + b;
}
let multiply; // 변수는 선언부만 끌어올린다
console.log(sum(1, 2));
console.log(multiply(3, 4));
multiply = function (a, b) { // 변수의 할당부는 원래 자리에 남겨둔다.
return a * b;
}
위와 같이 함수 표현식
은 변수의 할당부는 원래 자리에 남겨두는 함수 표현식의 특징으로 코드를 작성할때 안전한 방법이 될 수 있다.
반면에, 함수 선언문
은 호이스팅되어 올라가면서 같은 이름의 함수는 덮어쓰기 때문에 앞서 선언한 함수를 사용할 수 없어 위험할 수 있다.
오직 함수에 의해서만 스코프가 생성
.현재 호출된 함수가 선언될 당시
의 LexicalEnvironment 를 참조한다.
선언될 시점은 과거에
콜 스택 상에서 어떤 실행 컨텍스트가 활성화된 상태일 때뿐이며 어떤 함수를 선언하는 행위 자체도 하나의 코드에 지나지 않으며, 모든 코드는 실행컨텍스트가 활성화 상태일 때 실행되기 때문이다.