Javacsript si Wierd - 2-4. Hoisting-thumbnail

Javacsript si Wierd - 2-4. Hoisting

Hoisting
442

Hoisting

"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: 타입과 문법, 스코프와 클로저』