First written: 23-02-16
Uploaded: 23-08-04
"Compiler, Engine, Scope" 글을 보고왔다면, 아마 이번 장은 누워서 떡먹기 쯤으로 여겨질 수도 있다.
a = 1;
var a;
console.log(a); // 1
Compiler, Engine, Scope의 대화를 기억해보면, Compiler가 먼저 작업을 시작하는데, Compiler는 선언문에 대해서만 처리를 하고, Engine이 실제 할당을 했던 걸 기억할 수 있다. 그러므로 코드 순서에 따라 위 코드를 재구성하면 아래와 같다.
var a;
a = 1;
console.log(a); // 1
이렇게 마치 선언문만 똑 떼어서 위로 올려보내진 것과 같은 효과가 일어나는 것을 Hoisting
이라고 한다.
변수 말고 함수에 대해서도 알아보자. 먼저 함수 선언문이다.
fn();
function fn() {
/* ... */
}
Hoisting
을 적용하면 아래와 같다.
function fn() {
/* ... */
}
fn();
이번에는 함수 표현식을 보자.
fnOuter();
fnInner();
var fnOuter = function fnInner() {
/* ... */
}
이 코드에 Hoisting
을 적용하면 아래와 같다.
var fnOuter;
fnOuter(); // Uncaught TypeError: fnOuter is not a function
fnInner(); // Uncaught ReferenceError: fnInner is not defined
fnOuter = function() {
var fnInner = /* ...self... */
}
우선 바깥에 존재하던 함수는 위로 끌어올려져 var fnOuter;
가 선언된다. 하지만 할당된 값이 없는 채로 함수처럼 호출되어 TypeError가 발생한다.
반면 함수 표현식에 있던 이름은 scope가 global scope
가 아닌 fnOuter scope
에 속하게 되므로 바깥에서 접근하려고 해도 접근할 수 없어 ReferenceError를 던지게 된다.
참고 서적 : 카일 심슨, 2017, 한빛미디어, 『YOU DON'T KNOW JS: 타입과 문법, 스코프와 클로저』