Javascript

hoisting(호이스팅)

M9M9 2020. 10. 16. 21:22

자바스크립트에는 호이스팅이라는 것이 존재한다.

 

호이스팅이란 어느 위치에 선언되었는지 상관하지 않고 유효 범위의 맨 위로 선언을 끌어올리는 것이다.

이때, 할당 되어있는 부분은 끌어올리지 않고 선언 부분만 끌어올리게 된다.

그래서 선언과 할당이 분리된다고도 한다.

 

호이스팅이 일어나는 대상으로는 두가지가 있다.

 

첫째, var 변수

 

둘째, 함수  

 

이 두가지가 자바스크립트에서 호이스팅이 일어난다.

 

그러면 var변수부터 살펴보겠다.

 

 

var hoisting

console.log(test); // undefined

test=4;
console.log(test); //4
var test;

처음에 test변수를 선언하지도 않고 console.log를 통해 출력했는데 undefined가 출력됐다.

 

에러가 발생하는 상황이라고 인식할 수 있지만, 자바스크립트의 var는 hoisting 때문에 그렇지 않다.

 

 

var test;

console.log(test); // undefined

test=4;
console.log(test); //4


//hoisting이 됐다고 가정한 코드

var는 hoisting 되기 때문에 가장 맨 위로 선언이 끌어올려진다. 

그래서 console.log(test)가 오류가 발생하지 않고,

선언은 되어있는데 값이 할당이 안된 undefined가 출력되는 것이다.

 

하지만 이때, 선언 부만 끌어올려지고 할당 부분의 위치는 변경되지 않는다.

그래서  test=4를 할당 후에 console.log(test)를 출력할 때 4가 출력되는 것이다.

 

 

 

 

함수 hoisting

 

두 번째로 함수가 호이스팅 된다.

 

 

 

먼저, 함수 선언문일 경우

test();

function test(){
    console.log('test');
}

//restult:'test'

이 코드의 결과는 test가 출력된다.

 

그 이유는 test()가 위에 먼저 실행됐지만,

함수 선언문 같은 경우는 호이스팅이 발생해 최상단으로 함수가 이동하게 된다.

 

그 결과 호이스팅이 발생할 때의 코드는

function test(){
    console.log('test');
}
test();

//restult:'test'

이렇게 test 함수가 맨 위로 끌어올려지게 된다. 그래서 test를 먼저 실행해도 정상적으로 test() 함수가 실행되는 것이다.

 

 

함수 표현식

 

함수 선언문과 달리 함수 표현식일 경우에는 호이스팅이 되지 않는다.

fc();
var fc=function(){
    console.log('test');
}

result:"test is not a function

그 이유는 

 

함수 표현식이 변수에 함수를 할당한 것이다.

그래서 결국 변수를 선언한 것이므로,

변수가 호이스팅 되고, 할당한 함수는 그 위치에 있다.

 

코드로 보자면

var fc;
fc();

fc=function(){
    console.log('test');
}

result:"test is not a function

호이 스팅으로 인해 변수가 위로 올라간 후, 할당이 안된 상태에서 fc를 호출한 모습을 볼 수 있다.

이러므로 에러가 발생하는 것이다.

 

 

 

 

그렇다면 함수 내부에서는 호이스팅이 어떻게 진행될까?

function m9(){
    console.log(value);  //undefined
    
    value=3;
    console.log(value);  //3

    var value;
    console.log(value);  //3 


    inner(); //내부함수

    function inner(){
        console.log('내부함수'); 
    }

    fc(); //Cannot access 'fc' before initialization
    const fc=function(){
        console.log('함수 표현식 일때');
    } 
    
}
m9();

위에서 설명한 결과와 같다.

 

이것을 hoisting 된 상태의 코드로 변경한다면

 

function m9(){
    var value;
    const fc;
    
    function inner(){
        console.log('내부함수'); 
    }
   
    console.log(value);  //undefined
    
    value=3;
    console.log(value);  //3

    var value;
    console.log(value);  //3 

    inner(); //내부함수

    fc(); //Cannot access 'fc' before initialization
    
    fc=function(){
        console.log('함수 표현식 일때');
    } 
    
}
m9();

이렇게 변하게 된다.

 

 

 

 

 

함수와 var의 hoisting 우선순위

var가 함수 선언식보다 더 위로 끌어올려진다.

 

그래서 바로 위에 코드를 참고하면 호이스팅 됐을 때, 함수 선언문보다 변수가 더 위에 위치한 모습을 볼 수 있다.

 

 

 

 

var와 함수의 이름이 동일할 경우의 hoisting

 

이와 같이 함수의 이름과 var 변수의 이름이 같은 경우

변수에 값이 할당되어있지 않다면, 함수가 변수를 덮어 씌우게 된다.

 

반대로 변수가 함수를 덮어 씌우지는 않는다.

var a=1;



function a(){
    console.log('a입니다'); 
}


var b=2;

function b(){
    console.log('b입니다');
}

function fc(){
    console.log('test');
}

var fc;

console.log(a); //1
console.log(b); //2
console.log(fc); //function fc

이 코드를 호이스팅으로 바꾸면

 

 

var a=1;
var b;
var fc;



function a(){
    console.log('a입니다'); 
}


b=2;

function b(){
    console.log('b입니다');
}

function fc(){
    console.log('test');
}


console.log(a); //1
console.log(b); //2
console.log(fc); //function fc //var 변수에 값이 할당되어있지 않고, var변수와 이름이 같으므로 함수가 값을 덮어 씌운다.

참고로 let이나 const일 경우 이런 일이 발생하지 않는다.

 

 

 

 

 

 

 

 

 

애초에 let이나 const를 사용해서 호이스팅이 일어나지 않게 막고,

 

함수 같은 경우도 위에다 선언하고 아래에다 호출하여

호이스팅이 일어날 만한 상황조차 만들지 말자.

 

괜히 코드 복잡해진다.

'Javascript' 카테고리의 다른 글

화살표 함수 this(arrow function this)  (0) 2020.11.11
비교 연산자  (0) 2020.10.16
var와 let 그리고 const  (0) 2020.10.15
자바스크립트 객체  (0) 2020.08.21
데이터 타입  (0) 2020.08.19