변수 호이스팅, 그리고 초기화 initialize, Temporal Dead Zone
초기화는 변수선언시에 최초로 undefined가 할당이 되는것을 말한다.
먼저 그림으로 살펴보면,
let value = 'hello world';
라는 코드가 실행되면 먼저 식별자 value가 가르키는 메모리주소1이 생성되고 이 주소가
가르키는 메모리공간에는 undefined가 할당된다.
그 후, 이 식별자 value는 메모리주소2를 가르키게되고 이 메모리주소 2가 가르키는
메모리공간에는 'hello world'라는 데이터가 재할당된다.
# 먼저 선언하지 않은 변수를 참조해보자.
console.log(babo);
ReferenceError이 발생된다. 내용은 변수 babo가 정의되지 않았다라는 것이다.
# 선언보다 참조를 먼저 하는 경우 var (호이스팅)
console.log(babo);
var babo = "123";
코드상으로 봤을때 변수선언보다 참조를 먼저하는 경우의 코드이다.
코드가 순서대로 실행된다고 봤을때, 이는 참조시에 불러오는 babo가 없으니 Reference Error가 떠야 할것이다.
하지만 코드를 실행해보면
이렇게 undefined가 찍혀나온다.
이것을 바로 호이스팅이라고 한다.
자바스크립트 엔진은 런타임시 모든 선언을 코드 최상단으로 끌어올린다.
때문에 최초 var babo;라는 코드가 코드에서 가장 먼저 실행되는것이다.
이전 '변수와 메모리 관계'포스팅에서 설명했듯이
var babo = "123";
라는 코드는
var babo;
babo = '123';
라는 코드로 나뉘어 실행되기떄문에 선언부분인 var babo; 부분만 호이스팅이되어
undefined가 출력되는것이다.
즉 자바스크립트는 모든 선언문을 호이스팅하여 런타임시 가장 먼저 실행시킨다.
# 선언보다 참조를 먼저 하는 경우 let (호이스팅)
위에서 분명 '모든' 선언을 호이스팅하여 런타임때 먼저 실행한다고 하였다.
그럼 let으로 호이스팅이 되는지 확인해보자.
console.log(babo);
let babo = "123";
Reference Error가 뜨게된다.
응? 분명 호이스팅되어 let babo; 라는 부분이 런타임 최상단으로 옮겨졌고 처음엔 undefined가 할당이 되어
var호이스팅처럼 undefined가 출력되야하는데 에러가 뜨게된다?
그럼 let은 호이스팅이 되지 않는것인가?
# let과 var선언의 호이스팅 차이점 (Temporal Dead Zone)
먼저 변수가 선언이 되면 이 변수는 식별자가 되고, 이 식별자가 가르키는 메모리주소가 생긴다.
이 메모리주소는 메모리공간을 가르키며, 이 메모리공간에 undefined가 할당이 된다.
이는 let과 var의 선언문 모두 같다.
var babo_from_var;
let babo_from_let;
console.log(babo_from_var); //undefined
console.log(babo_from_let); //undefined
이 코드는 var과 let 모두 똑같이 undefined를 출력하는걸 볼 수 있다.
위 두가지 그림은 let과 var의 선언차이를 설명한다.
여기서 중요한점은
var은 런타임시 선언과 초기화 과정이 모두 실행된다는 점이고
let은 런타임시 선언과 초기화 과정의 시간차가 존재한다는 것이다.
때문에 그림에서 TDZ(Temporal Dead Zone)라고 적혀있는곳이 이런 시간차를 가르킨다.
let과 var 둘다 변수선언(식별자)는 호이스팅시 끌어올려지지만,
이 식별자가 가르키는 메모리주소가 생성되고 초기화까지 되는 시점이 서로 다르다는 것이다.
때문에 let 호이스팅 테스트 코드에서 reference에러의 설명이
initialization(초기화)되기전에 babo라는 식별자가 가르키는 메모리주소, 메모리공간에 접근할수 없다는
에러메세지가 뜨는것이다.
만약 let선언문이 호이스팅이 되지 않았다고 한다면,
이렇게 babo라는 변수(식별자)가 정의되지 않았다고 뜰것이다.
즉 선언문은 호이스팅시에 먼저 올라가지만, 초기화의 차이로 var과 let이 차이가 생기는 것이다.
# const
const babo;
const로 변수를 선언하는 위 코드를 실행하면
이렇게 syntax Error가 뜬다.
애초에 const 선언문은 재할당을 금지시키므로 코드처럼 할당하는 코드를 같이 써주지 않으면
구문오류(syntaxError)가 뜨는것이다.
그런데 의문을 가질것이다.
const babo = 'hello const';
위와 같이 선언과 할당을 동시에 하는 모든 코드는
초기화(첫 undefined할당)와 재할당(hello const)으로 두번으로 나눠진다고 하였다.
엄밀히 말하면 const 선언또한 이렇게 나뉘어진다.
하지만 런타임시 const 선언문만 있을경우 구문오류로 막아놓은것이다.
자바스크립트의 모든 변수선언은 초기화로 undefined가 할당이 된다.
console.log(babo);
const babo = "hello const";
이렇게 해도
초기화가 되기전에 식별자에 접근할수 없다는 에러가 뜬다.