console.log(variable); //undefined
var variable;
호이스팅이란 선언문이 코드의 선두로 끌어올려진 것처럼 동작하는 자바스크립트의 특징이다. 자바스크립트 엔진은 코드를 한 줄씩 순차적으로 실행(런타임) 하기에 앞서 소스코드의 평가 과정을 거치고, 이때 소스코드 내의 선언문을 찾아 먼저 실행한다. (이 부분은 실행 컨텍스트를 알면 더 깊게 이해할 수 있다. 관련 내용은 추후에 작성)
따라서 위 코드에서 variable을 선언한 부분이 먼저 실행되고, 그 이후 출력을 수행한다.
호이스팅을 이해하기 위해서는 변수 메커니즘에 대한 이해가 필요하다.
변수는 선언=> 초기화 => 할당의 단계를 거치게 된다. var 키워드와 let 키워드는 이 단계를 수행하는 과정이 서로 다르고 이에 따라 호이스팅의 양상도 다르게 나타난다.
var 키워드로 선언한 변수는 런타임 이전에 선언 단계와 초기화 단계를 거친다.
console.log(v);//undefined
v = 100;
console.log(v);//100
var v = 200;
console.log(v);//200
위 코드를 보고 실행 순서와 결과를 예상해보자.
먼저 런타임 이전에 var v에서 v의 선언과 초기화가 이루어진다. 더 이상 선언하는 부분이 없다면 첫 번째 줄부터 실행한다. 처음 console에서 v는 초기화까지 이루어진 상태이고 아직 값은 할당되지 않았으므로 undefined가 출력된다. 그다음 v에 100이 할당되고 이에 따라 두 번째 출력의 값은 100이 된다. 그다음 200이 할당되고 마지막에는 200이 출력된다.
let 키워드로 선언한 변수는 런타임 이전에 선언까지만 실행된다. 이후 런타임에 다시 선언문에 도달하면 비로소 초기화가 이루어진다. let 키워드에서 선언부터 초기화 단계까지의 간격을 일시적 사각지대(Temporary Dead Zone)라고 부른다.
console.log(v); //Cannot access 'v' before initialization
let v;
console.log(v);//undefined
v = 100;
console.log(v);//100
런타임 이전에 먼저 let v가 실행되고, 선언이 이루어진다. 첫 번째 출력에서는 초기화가 아직 진행되지 않았으므로 에러가 발생했다. 이후 let v에 다시 도달했을 때 초기화가 진행되어 두 번째 console에서는 undefined가 출력되었다. 마지막으로 100을 할당하고, 100을 출력했다.
let 키워드를 사용하면 호이스팅이 발생하지만 발생하지 않는 것처럼 보인다. 이는 앞서 설명했 듯 런타임 이전에는 선언 단계까지만 이루어지기 때문이고, 또한 이는 let 키워드를 사용해야 할 근거가 된다.
(호이스팅은 개발자 입장에서 혼란을 가중시킨다. 호이스팅이 필요한 이유가 뭘까?)
함수 호이스팅은 선언문이냐, 표현식이냐에 따라 함수의 생성 시점이 다르기 때문에 다른 방식으로 호이스팅된다.
선언문으로 함수를 정의하면 런타임 이전에 함수 객체가 생성된다. 자바스크립트 엔진은 함수 이름과 동일한 이름의 식별자를 생성하고 생성된 함수 객체를 식별자에 할당한다.
변수로 치면 선언, 초기화, 할당이 모두 이루어진 것이다.
console.log(add(2, 3)); //5
function add(x, y) {
return x + y;
}
다음 순서로 작동한다.
함수 표현식으로 함수를 작성하면 변수 호이스팅이 발생한다.
console.log(add);//undefined
var add = (x, y) => {
return x + y;
};
console.log(add(2, 3));//5
다음 순서로 변수 호이스팅처럼 작동한다.
var가 아닌 let을 사용하면 변수 호이스팅에서 let을 사용한 것처럼 작동한다.