개몽가

[JavaScript] 익명함수와 선언적 함수, 호이스팅(hoisting) 본문

Skill/JavaScript

[JavaScript] 익명함수와 선언적 함수, 호이스팅(hoisting)

개몽가 2020. 4. 11. 16:17

프로젝트에서 JavaScript에 함수를 하나 추가했는데 이상한 현상을 발견했다.

    var exam = function(){ ....};
    
이런식으로 함수를 밑에다가 추가했고, 위의 또다른 함수에서 exam함수를 호출했다.
실행해보고 나니 화면이 멈췄고, console창에는 exam 함수를 찾을 수 없다는 오류가 났다.

주 언어가 Java이다 보니, public인 클래스 안의 어디에서나 만들고 호출해도 호출이 됐느데, JavaScript는 그렇지 않으니까 당황스러웠다...
구글링을 해보았고, 변수에 함수를 담는 것의 차이가 있다는 것을 알았다.

내가 만든 함수는 이름없는 함수 즉, 익명함수였고 
익명함수를 사용하기 위해 exam 변수 함수를 넣어주는 작업을 했던 것이다.

자바처럼 함수를 만드는 것은 분명 함수 이름이 있어야했고 선언적 함수라고 한다고 한다.

    function exam(){ .... }; //선언적 함수 (이름 명시!)

실제, 프로젝트에서는 이렇게 익명함수, 선언적 함수를 마구잡이로 쓰고있었다. 생각해보면 통일성이 없어보이겠지만 그렇지 않았다면 나는 익명하수와 선언적 함수의 차이를 몰랐을지도 모르겠다.

아무튼,
웹브라우저는 자바스크립트의 내용을 위에서부터 한줄 씩 읽기 전에 선언적 함수부터 먼저 읽는다는 것이었고
이말은 즉, 위에서 내가 취했던 익명함수를 밑에서 만들고 이보다 먼저 발생하는 이벤트 함수에 익명함수를 호출하면 웹브라우저는 익명함수는 없다고 판단하는 게 당연하다는 것이다.

    function fuc(){  exam(); }; //웹 브라우저가 exam 함수를 찾을 수 없음
    var exam = function() { alert("시험"); }; 


익명함수를 변수에 선언하기 이전에 호출했기 때문에 오류가 발생하는 것.
*익명함수 : 런타임 때 실행, 글로벌 영역에 미등록
*선언적함수 : 글로벌 영역에 등록되어있어 런타임 전에 등록

여기서 연결되는 단어가 있는데 바로  *호이스팅(Hoisting)* 이다.
익명함수와 선언적함수의 차이는 호이스팅에서 발생한다.
호이스팅이란 인터프리터 자바스크립트를 해석할게 될 때 글로벌영역의 선언된 코드를 최상의 Scope로 끌어올리는 것을 말한다고 한다. 
주의할 점은 호이스팅은 선언되는 변수들은 호이스팅하지만 변수에 할당된 값까지 호이스팅되지 않는다는 점이다. (값 할당은 런타임 때!! , 선언은 자바스크립트 엔진이 제일 먼저!)

    fuc();
    function fuc(){...};
    호출이 되는 것은 fuc함수에 대한 선언을 호이스팅하여 global 영역에 등록시켜서 함수 호출이 정상적으로 이루어짐
    
    
    
    exam();
    var exam = function(){...};
    변수에 함수를 할당하는 구조이기 때문에 호이스팅되지 않음. -> global 영역에 미등록됨