호이스팅(hoisting)

개념

호이스팅(hoisting)은 단어 뜻과 같이 Javascript 엔진에서 javascript file을 parsing 단계에서 변수, 함수선언문에 대하여 스코프 상단으로 끌어올리는 것을 말한다.

  • 실제 code가 변경되는 것이 아닌 엔진 내부에서 가상적으로 끌어올려 code 해석 및 실행 함

예시

아래 코드에서 a라는 변수를 선언하였는데 선언 이전에 a라는 변수를 호출하는 코드가 존재 시 ReferenceError가 아닌 undefined가 출력된다.

//사용자 script
console.log(a); // undefined
var a = 10;
console.log(a); // 10
//javascript 엔진 parsing 시
var a; //호이스팅 O
console.log(a); // undefined
a = 10;
console.log(a); // 10
  • Javascript 엔진에서 parsing하는 경우 위 코드와 같이 변수선언을 최상단에서 하며 값 할당의 경우 기존 자리에서 진행한다.

const, let

ES6에서 추가된 const, let의 경우 호이스팅이 되지 않는다. 아래와 같이 code가 있는 경우 해당 코드는 ReferenceError가 발생한다.

//사용자 script
console.log(a); // ReferenceError: Cannot access 'a' before initialization
console.log(b); // ReferenceError: Cannot access 'b' before initialization
const a = 10;
let b = 20;
console.log(a); // 10
console.log(b); // 20
//javascript 엔진 parsing 시
console.log(a); // ReferenceError: Cannot access 'a' before initialization
console.log(b); // ReferenceError: Cannot access 'b' before initialization
const a = 10; //호이스팅 X
let b = 20; //호이스팅 X
console.log(a); // 10
console.log(b); // 20

함수

함수의 경우 함수 선언문의 경우 호이스팅이 되지만 함수 표현식의 경우 호이스팅이 되지 않는다.

//사용자 script
echo(); // "함수선언문"
echo2(); // TypeError: echo2 is not a function

function echo() // 함수 선언문
{ 
  console.log("함수선언문");
}
var echo2 = function() //함수 표현식
{
  console.log("함수표현식");
}
//javascript 엔진 parsing 시
var echo2; // 변수에 대한 호이스팅 O
function echo() // 함수에 대한 호이스팅 O
{ 
  console.log("함수선언문");
}

echo(); // "함수선언문"
echo2(); // TypeError: echo2 is not a function

echo2 = function() //여기서 함수를 할당한다.
{
  console.log("함수표현식");
}

내부 함수의 경우 외부 함수 내 스코프에서 최상단으로 호이스팅이 발생한다.

  • 내부 함수가 함수 선언문인 경우

    //사용자 script
    function outerFn()
    {
    var inner = innerFn();
    console.log(typeof inner); //function
    console.log(inner); // "inner 함수선언문"
    function innerFn()
    {
        return "inner 함수선언문";
    }
    }
    
    outerFn();
    //javascript 엔진 parsing 시
    function outerFn()
    {
    var inner; //호이스팅 O
    
    function innerFn() //호이스팅 O
    {
      return "inner 함수선언문";
    }
    
    inner = innerFn(); //할당
    console.log(typeof inner); //function
    console.log(inner); // "inner 함수선언문"
    }
    
    outerFn();
  • 내부함수가 함수 표현식인 경우

    //사용자 script
    function outerFn()
    {
    console.log(inner); // undefined
    var inner = innerFn(); //함수 호출
    
    var innerFn = function()
    {
        return "inner 함수표현식";
    }
    }
    
    outerFn();
    //javascript 엔진 parsing 시
    function outerFn()
    {
    var innerFn; // 호이스팅 O
    var inner; // 호이스팅 O
    console.log(inner); // TypeError: inner is not a function
    var inner = innerFn(); //함수 호출
    
    var innerFn = function()
    {
        return "inner 함수표현식";
    }
    }
    
    outerFn();
  • const, let으로 함수표현식을 사용 시 호이스팅이 발생되지 않으므로 사용자 script 코드와 동일하게 해석한다.

규칙

  1. 변수, 함수가 동일한 이름인 경우

    • 변수가 함수보다 상위로 호이스팅
    • 변수에 값이 할당되는 경우 함수 선언문을 덮어쓴다.
    • 변수에 값이 할당되지 않는 경우 함수가 할당된다.
    //사용자 script
    var a = 10;
    var b;
    
    function a()
    {
      console.log("함수a");
    }
    function b()
    {
      console.log("함수a");
    }
    
    console.log(typeof a); // number
    console.log(typeof b); // function
    //javascript 엔진 parsing 시
    /*변수가 함수보다 상위로 호이스팅*/
    var a; // 호이스팅 O
    var b; // 호이스팅 O
    
    /*함수가 변수를 덮어씀*/
    function a() // 호이스팅 O
    {
      console.log("함수a");
    }
    function b() // 호이스팅 O
    {
      console.log("함수a");
    }
    
    /*값 할당을 통해 함수를 덮어씀*/
    a = 10; //a:function -> a:number
    
    console.log(typeof a); // number
    console.log(typeof b); // function

참고

© 2021 AnGwangHo, Built with Gatsby