
변수를 사용하기 전에 준비하는 데는 3단계로 나눠진다.
변수 할당: 선언 단계 > 초기화 단계 > 할당 단계
선언 단계 : 변수를 실행 컨텍스트의 변수 객체에 등록하는 단계
초기화 단계 : 실행 컨텍스트에 존재하는 변수 객체에 선언 단계의 변수를 위한 메모리를 만드는 단계로 이 단계에서 할당된 메모리에는 undefined로 초기화된다.
할당 단계 : 사용자가 undefined로 초기화된 메모리의 다른 값을 할당하는 단계
var a = "a";
console.log(a); // "a"
var a = "aa";
console.log(a); // "aa"
위처럼 이중으로 선언해도 에러가 발생하지 않아 마음대로 선언하여 사용할 수 있다. 하지만 선언을 여러 번하게 되면 어디에 어떤 변수로 적용되는지 추적하기가 어려워지고 그러면 에러가 발생했을 때 원인을 해결하기도 어려워진다.
자바스크립트 엔진은 전체 코드를 한 번 쓱 읽어보고 함수선언문을 해석하고, 변수를 초기화한 후, 코드실행 순서로 진행된다.
이 때, 변수는 최상단에서 선언된 것처럼 작동하여 실제로 선언하기 전에 호출되어도 에러가 발생하지 않게 된다. (var의 경우만 해당, let과 const에 대해서는 추후 설명)
hoisting: 인터프리터가 변수와 함수의 메모리 공간을 선언 전에 미리 할당하는 것
“스코프” 내부 어디서든 변수 선언은 최상위에서 선언된 것처럼 행동
변수 선언만 hoisting이 가능함 (초기화는 대상 X)
—> hoisting: 선언만 hoisting됨. 할당은 hoisting 되지 않음
var는 선언하기 전에 호출해도 에러가 나지 않는다. <-- hoisting
console.log(name);
var name = “Mike”;
//(var name; << -- 최상단으로 hoisting됨)
console.log(name); //undefined
var name = “Mike”;
var는 위의 경우 에러가 나지 않지만 let과 const는 에러 발생함.
let&const - 블록 스코프 block-scoped
let - 선언단계, 초기화 단계, 할당 단계가 별도로 이루어질 수 있음
let name;
name = "MIKE";
const - 선언+초기화+할당이 한번에 이루어져야함
//const name;
//name = "MIKE"; >> ERROR
const name = "MIKE";
let과 const에서도 hoisting이 일어나지만
Temporal Dead Zone (TDZ)의 영향을 받기 때문에 작동하지 않는다.
따라서 선언하기 전에 변수를 호출하면 ReferenceError가 발생함.
TDZ: 일시적인 사각지대는 스코프의 시작 지점부터 초기화 시작 지점까지의 구간
TDZ 시맨틱은 선언 전에 변수에 접근하는 것을 금지한다.
var와 다르게 초기화가 되기전까지 TDZ라는 곳 안에 있어 초기화(혹은 할당)이 될 때까지 잠시 죽어있는 상태로 선언 전에 참조할 수 없다.
선언 전에 변수를 사용하는 것을 허용하지 않는 비개념상의 공간이라고 볼 수 있다.
이러한 결과로 코드를 예측가능하게 하고, 잠재적 에러를 방지할 수 있다.
let age = 30;
function showAge(){
//let age = 20; hoisting되지만 TDZ의 영향으로 실행되지 않음
console.log(age);
let age = 20;
}