실행컨텍스트 생성시 Variable Environment에 정보를 먼저 담고, 이를 복사해 Lexical Environment를 만든다. 그 이후 Lexical Environment를 주로 사용한다.
Variable Environment와 Lexical Environment의 내부는 environment Record와 outer Environment로 구성되어있다.
https://developer.mozilla.org/en-US/docs/Glossary/Hoisting
function a() {
console.log(b); // (1)
var b = 'bbb'; // 수집 대상 1(변수 선언)
console.log(b); // (2)
function b() {} // 수집 대상 2(함수 선언)
console.log(b); // (3)
}
a();
위와 같은 코드를 호이스팅 개념을 적용해 바꿔보자
function a() {
console.log(b); // (1)
var b = 'bbb'; // 수집 대상 1(변수 선언)
console.log(b); // (2)
function b() {} // 수집 대상 2(함수 선언)
console.log(b); // (3)
}
a();
위와 같은 코드를 호이스팅 개념을 적용해 바꿔보자
function a() {
var b;
var b = function b() {} // <-- 바뀐 부분
console.log(b); // (1)
var b = 'bbb';
console.log(b); // (2)
console.log(b); // (3)
}
// console.log의 결과는 차례대로 함수, 'bbb', 'bbb'가 나온다.
변수는 선언부를 끌어 올리고, 함수 선언은 전체를 끌어올리기때문에 위 코드처럼 바뀌었다.
짧게 짚고 넘어가기 - 함수 선언문과 함수 표현식
console.log(sum(1,2));
console.log(multiply(3,4));
// 함수 선언문
function sum(a, b) {
return a + b;
}
// 함수 표현식
var multiply = function(a, b) {
return a * b;
}
// 호이스팅이 적용된 코드
var sum = function sum(a, b) {
return a + b;
}
var multiply;
console.log(sum(1, 2));
console.log(multiply(3, 4));
multiply = function(a, b) { // 변수 할당부는 원래 자리에 남김
return a * b;
}
// 결과: multiply is not a function Error
스코프를 안에서 바깥으로 검색해나가는 것
LexicalEnvironment의 outerEnvironmentReference가 가능케한다.
outerEnvironmentReference는 호출된 함수의 선언될 당시의 LexicalEnvironment를 참조하기 때문이다.
따라서 무조건 스코프 체인상에서 가장 먼저 발견된 식별자에만 접근 가능하게 된다. (outerEnvironmentReference는 연결 리스트 형태를 띄게 된다!)
var a = 1;
var outer = function() {
var inner = function() {
console.log(a);
var a = 3;
}
inner();
console.log(a);
}
outer();
console.log(a);
코드 실행 동작 과정
console.log(a)
로 식별자 a에 접근하려하지만 a에는 아무 값이 할당되있지 않아 undefined
를 출력한 다음, a에게 3을 할당하게 되면서 inner함수 실행이 종료된다.console.log(a)
로 a에 접근을 시도한다. outer실행컨텍스트의 LexicalEnvironment의 environmentRecord에는 a가 없으므로, outer의 outerEnvironmentReference에 있는 environmentRecord로 넘어가서 a를 찾는다. 이때 outer 실행컨텍스트의 outerEnvironmentReference는 전역 컨텍스트가 되고, 전역 컨텍스트의 environmentRecord에는 a가 있으므로 a의 값을 반환하게 된다. 그러므로 1
이 출력된다.console.log(a)
를 실행하려 한다.1
이 출력된다.Refer - Core Javascript