JavaScript의 hoisting(호이스팅)

호이스팅은 JavaScript에서 실행 컨텍스트가 생성될때, 변수나 함수 선언을 최상단에 끌어올린 것 처럼 동작하는 것을 말합니다.

변수의 호이스팅

function foo(){
  console.log(bar);
  var bar = 1;
}

foo(); // undefined

위 함수를 실행시키면 undefined가 찍힙니다.

조금 더 이해하기 쉽게 호이스팅 된 후 foo 함수의 모습을 적어보겠습니다.

function foo(){
  var bar; // 호이스팅됨
  console.log(bar);
  bar = 1;
}

foo();

변수 할당이 아닌 선언부만 최상단으로 끌어올렸기 때문에 bar를 콘솔에 찍으려고 하면 undefined가 찍히게 됩니다.

만약 bar 변수가 var가 아닌 let, const로 선언되었다면 Temporal Dead Zone(TDZ)에 의해 reference error가 발생합니다. 자세한 내용은 이 글을 참고해주세요!

var bar = 1;

function foo(){
  console.log(bar);
  var bar = 3;
}

foo();

위 코드를 실행하면 어떻게 될까요?

다시 한번 호이스팅 된 후의 버전으로 살펴보겠습니다.

var bar = 1;

function foo(){
  var bar;
  console.log(bar);
  bar = 3;
}

foo(); // undefined

전역변수가 선언되었더라도 foo 함수 컨텍스트 안에서 새로 선언된 bar의 선언부가 위로 끌어올려지기 때문에 undefined가 찍히게 됩니다.

함수의 호이스팅

변수의 경우 선언부가 호이스팅 되었다면, 함수의 경우 함수 선언 전체가 호이스팅 됩니다.

var bar = 1;

function foo(){
  console.log(bar);
  var bar = 3;
  console.log(bar);
  function bar() {}
  bar = 'gg';
  console.log(bar);
}

foo();

이번에 이 코드를 실행하면 어떻게 될까요?

이번에도 호이스팅 된 후 모습을 한번 봅시다!

var bar = 1;

function foo(){
  var bar;
  function bar() {};
  console.log(bar); // f bar()
  bar = 3;
  console.log(bar); // 3
  bar = 'gg';
  console.log(bar); // 'gg'
}

foo();

변수는 선언부가 따로 떨어져서 호이스팅 되고 함수의 경우 함수 선언 전체가 호이스팅되기 때문에 위와 같은 결과가 나타납니다.

함수 표현식과 함수 선언식

sum(1,2) // 3
substract(2,1); // substract is not a function

function sum(a,b){ // 함수 선언식
  return a+b;
}

var substract = function(a,b){ // 함수 표현식
  return a - b
}

이전 포스트에서 함수 표현식은 호이스팅이 되지 않는다고 했었는데, 이제 왜 함수 표현식은 호이스팅이 되지 않는지 알것 같습니다.

함수 표현식은 함수를 변수에 할당해준것이기 때문에 위 코드의 호이스팅 후의 모습은

var substract;
function sum(a,b){
  return a+b;
}

sum(1,2)
substract(2,1);

substract = function(a,b){
  return a - b
}

이런 모습이 되겠네요. 비어있는 변수인 substract를 함수처럼 호출하라고 했기 때문에

substract is not a function 에러가 발생했던 것입니다.


Written by@Mengkki
common fangirl

GitHub