Javascript 에서 호이스팅이란 변수나 함수의 선언이 끌어올려지는 것처럼 보이는 것을 말한다.
(실제로 끌어올려지지는 않는다.)
Javascript 는 문을 실행하는 런타임 이전에, 코드 평가 과정을 거치면서 코드를 실행하기 위한 준비를 한다.
이때 자바스크립트 엔진은 모든 선언문을 찾아서 먼저 실행한다. 이 때문에 선언문이 끌어올려져서 실행되는 것처럼 보이는 것이다.
console.log(a); // undefined
var a;
a = 10;
console.log(a); // 10;
JavaScript
복사
위 예제에서 a를 선언하기 이전에 값을 확인해보면 undefined 인 것을 확인할 수 있다.
var 로 선언된 변수는 선언과 동시에 undefined 로 초기화 되기 때문이다.
하지만 변수를 실행하기도 전에 참조할 수 있는 것은 직관적으로 자연스럽지도 않고, 문제를 일으킬 여지가 상당히 많아보인다.
ES6 이후 등장한 let 과 const 는 선언과 초기화를 나눠서 실행함으로써
호이스팅이 되지 않는 것처럼 보이게한다.
console.log(b); // Uncaught ReferenceError: b is not defined
let b;
console.log(b); // undefined;
b = 20;
console.log(b); // 20;
JavaScript
복사
위 예제에서 let 으로 선언한 변수 b 또한 호이스팅 되었지만, 선언만 되고 초기화는 되지 않았기 때문에 정의되지 않았다는 에러메세지가 뜬다.
선언문을 만났을 때 비로소 undefined로 초기화를 하고, 이후 재할당을 한 뒤 다시 값을 확인해보면 재할당한 값으로 바뀐 것을 확인할 수 있다.
console.log(c); // Uncaught ReferenceError: c is not defined
const c = 30;
console.log(c); // 30;
JavaScript
복사
const 로 선언한 변수도 마찬가지로 선언과 초기화가 나눠서 일어난다.
다만 const 로 선언된 변수는 재할당할 수 없기 때문에 코드를 작성할 때는 선언과 동시에 할당을 해주어야한다.
let과 마찬가지로 실제로 변수선언은 호이스팅되어서 런타임 이전에 이루어지지만, 초기화는 런타임에서 const 선언문을 실행하는 시점에 이루어진다.
let 으로 선언한 변수는 (코드 작성시 선언과 함께 초기화하지 않은 경우) undefined로 초기화 될 수도 있지만 const 으로 선언한 변수는 코드 작성시 선언과 초기화를 반드시 같이해주어야 한다는 점이 다르다.
결론
Javascript는 런타임 이전에 코드평가를 진행하면서 선언문을 미리 실행한다.
ES6 이전에는 변수가 선언됨과 동시에 undefined로 초기화 되었기 때문에 변수선언문 이전에 참조할 수 있었다.
ES6에서 등장한 let 과 const는 선언은 코드평가 과정에서 하지만 초기화는 런타임에서 변수선언문을 만났을때 이뤄지게 한다.
따라서 let과 const로 선언한 변수는 변수선언문 이전에 참조할 수 없고, 호이스팅이 되지 않는 것처럼 보인다.