본문 바로가기
JavaScript

호이스팅(Hoisting) 이해하기

by Vintz 2020. 11. 14.
반응형

호이스팅(hoisting)은 '변수와 함수의 선언부가 각자의 현재 스코프에서 물리적으로 코드 최상단으로 끌어올려지는 것'으로 많이들 알고계시지만 실제로는 그렇지 않습니다. 자바스크립트 엔진 내부적으로 처리를 그렇게 하는 것입니다. 

 

컴파일 단계에서, 여러분이 작성한 코드가 실행되기 바로 직전에 변수와 함수의 선언부들이 쭉 스캔 됩니다. 스캔 된 변수와 함수의 선언부들은 Lexical Environment로 불리는 자바스크립트의 자료구조 메모리상에 추가됩니다. 따라서 메모리에 존재하는 변수와 함수는 실제 선언 이전에 사용될 수 있습니다. - cada님의 벨로그 번역글

변수 및 함수 선언은 컴파일 단계에서 메모리에 저장되지만, 코드 그자체는 작성한 위치 그대로 존재합니다.


함수 선언식(function declaration)의 호이스팅

통상적인 함수 선언식(function declaration)

함수를 선언했고, 호출했습니다. 아무 문제없이 출력이 됩니다. 그렇다면 함수를 먼저 호출하면 어떻게 될까요?

함수를 먼저 호출했습니다.

그래도 이상없이 작동합니다. 함수를 선언하기 전에 함수를 호출했지만 여전히 작동을 합니다. 왜 그럴까요?

앞서 설명한 것처럼 자바스크립트 엔진이 내부적으로 작동하는 방식때문입니다. 즉, 함수 선언을 메모리에 저장했기 때문에 함수를 선언하기 전에 함수를 사용할 수 있게됩니다.

함수 표현식(function expression)의 호이스팅

통상적인 함수 표현식(function expression)

이번엔 todayFruit 변수를 선언하고 함수를 할당했습니다. 그 후 함수를 호출하면 정상적으로 작동합니다. 이번에도 함수를 먼저 호출하면 어떻게 될까요?

todayFruit가 함수가 아니라고하네요..

함수 선언은 호이스팅이 되지만 함수 표현식은 되지 않습니다. 자바스크립트는 선언만 호이스팅할 뿐, 초기값 할당에 대한 부분은 호이스팅하지 않습니다. 따라서 var todayFruit; 선언만 호이스팅 되고 그 값은 undefined로 지정됩니다. 즉, todayFruit는 함수가 아니라 변수로 취급됩니다(todayFruit is not a function).

변수의 호이스팅

위 설명과 더불어 var 변수에 대한 호이스팅을 더 알아보겠습니다. 

두 코드는 같은 방식으로 동작합니다.

자바스크립트는 선언된 변수와 함수만 호이스팅하기 때문에 위 예제의 두 코드는 같은 방식으로 동작합니다. 즉, 자바스크립트는 같은 동작 방식으로 처리합니다. 

그럼 let과 const는?

let과 const도 호이스팅이 됩니다. 하지만 var 선언부는 undefined로 초기화 되는 반면에 let과 const의 선언부는 uninitialized로 초기화 됩니다. 또한 let과 const는 'TDZ(Temporal Dead Zone)'에 의해 제약을 받게 됩니다. 즉, var와 달리 초기화되기 전에 접근하려하면 ReferenceError가 발생합니다. 이러한 특징은 잠재적 버그를 쉽게 찾아낼 수 있도록 합니다.

좀 더 엄격해진 let과 const

TDZ(Temporal Dead Zone)

TDZ(Temporal Dead Zone)는 let, const, class 구문의 유효성을 관리합니다.


참고

모던 자바스크립트에서의 호이스팅 - cada.log
let과 const는 호이스팅 될까? - yocee57
TDZ을 모른 채 자바스크립트 변수를 사용하지 말라 - 류선임님
오래된 'var' - 모던 자바스크립트 튜토리얼
반응형