어제는 const, let, var의 특징과 왜 var보다 const와 let을 사용하도록 권장되는지를 알아보았다. 오늘 공부할 내용의 var의 가독성을 떨어뜨리는 단점으로 거론되었고 이것이 일어나지 않는 것처럼 보이는 것이 const와 let의 장점이라고 하던 hoisting에 대해서 공부해 보려고 한다.
hoisting이란?
hoisting은 '끌어 올리기, 들어올려 나르기.' 라는 사전적 의미를 가지고 있다. 자바스크립트는 코드를 실행하기 전에 변수선언문, 함수 선언문들을 찾아 위로 끌어올리는 소스 평과 가정을 거친다. 이것을 hoisting이라고 한다.
hoisting이 일어나는 변수 선언문에는 var이 있고, 함수 선언문에는 function이 있다. class와 let, const는 non-hoisting로 보아도 무방하다. 이 hoisting때문에 변수나 함수를 선언하기 전에도 사용을 할 수 있는데, 이 때문에 코드의 가독성을 떨어뜨리기도 한다.
console.log(x) // error를 반환하는 대신 undefined를 반환한다.
var x = 1;
testHoisting('a'); // a
function testHoisting(param){
console.log(param);
}
hoisting이 되는 소스 평과 과정에서는 두가지 단계가 존재한다. 그건 바로 선언단계와 초기화 단계이다. 선언단계에서 스코프에 변수 식별자를 등록해 자바스크립트 엔진에 해당 변수를 알리고, 스코프에 등록된 변수에 기본값 undefined로 초기화를 진행한다. 여기서 중요한 것은 변수를 끌어올리는 것일 뿐이지 기본값까지 세팅을 해주는 것은 아니라는 것이다.
console.log(x) //undefined
var x = 'hello';
console.log(x) //hello
첫 줄 코드는 hoisting 으로 인해 에러가 반환되지는 않지만 그 다음줄에 세팅한 hello라는 초기값까지 같이 세팅되지 않았기 때문에 undefined로 값이 반환된다.
var과 function에서는 이 두 과정이 모두 진행되지만, non-hoisting으로 볼 수 있는 변수선언문과 함수선언문에서는 두 단계가 모두 진행되지 않는다. 이 말이 무슨 뜻이나면 소스 평가 과정을 거치면서 모든 스코프에 등록은 되지만 hoisting의 기본값이 세팅되지 않아, 에러를 반환하는 것이다. 이것을 한국어로는 일시적 사각지대(Temporal dead zone)이라고 한다. (class의 경우 hoisted 되지않지만, 일부 인터프리터에서는 hoisted는 되더라도 TDZ로 된다.)
let으로 예를 들어보겠다.
console.log(x) //reference Error
let x = 'hello';
console.log(x) //hello
먼저 인터프리터에서 변수x에 대한 등록은 마친 상태이나 초기값을 undefined로 세팅해 두지 않았기 때문에 첫 줄의 console.log()는 reference Error가 나타나게 된다. hoisted가 안된다고는 할 수는 없지만 되지 않는 것처럼 구현했기 때문에 가독성을 해치는 hoisting의 단점을 보완했다.
https://en.dict.naver.com/#/search?range=all&query=hoisting
https://developer.mozilla.org/en-US/docs/Glossary/Hoisting
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/var
https://youtu.be/ZU4MXkwDb9g