다들 var
,let
,const
의 차이에 대해 한번쯤 들어봤을 것이다.
var
은 호이스팅이 되지만 나머지는 안된다.
하지만 조금 더 자세히 알아보면 호이스팅 비슷하게 되고, 해당 값을 TDZ
라고 흔히 부른다.
실제로 인터프리터가 어떻게 let
혹은 const
에 대해서 호이스팅을 진행하는지 알아보려 한다(둘 다 동일).
--print-bytecode
옵션을 붙여 변환 가능function test(){
x = 1;
var x;
}
test();
에러 없음
function test(){
x = 1;
let x;
}
test();
ReferenceError: Cannot access 'x' before initialization
에러 발생
해당 함수에 해당하는 코드만 발췌했다.
21 S> 0x16e0b5891a50 @ 0 : 0d 01 LdaSmi [1]
0x16e0b5891a52 @ 2 : c4 Star0
0x16e0b5891a53 @ 3 : 0e LdaUndefined
39 S> 0x16e0b5891a54 @ 4 : a9 Return
단 4줄로 간단하게 변환되었다, 밑의 2줄의 경우 리턴값이 없기에 undefined
를 리턴하는 과정이다.
두 줄이 끝이다.
undefined
값을 먼저 넣어줘야 했지만 호이스팅 덕분에 잘 해결됐다. 0xfe43d7d1a68 @ 0 : 10 LdaTheHole
0xfe43d7d1a69 @ 1 : c4 Star0
21 S> 0xfe43d7d1a6a @ 2 : 0d 01 LdaSmi [1]
0xfe43d7d1a6c @ 4 : c3 Star1
0xfe43d7d1a6d @ 5 : 0b fa Ldar r0
23 E> 0xfe43d7d1a6f @ 7 : aa 00 ThrowReferenceErrorIfHole [0]
0xfe43d7d1a71 @ 9 : 19 f9 fa Mov r1, r0
36 S> 0xfe43d7d1a74 @ 12 : 0e LdaUndefined
0xfe43d7d1a75 @ 13 : c4 Star0
0xfe43d7d1a76 @ 14 : 0e LdaUndefined
39 S> 0xfe43d7d1a77 @ 15 : a9 Return
var보다 꽤나 복잡하게 되어있는데, 마지막 2줄은 이전과 마찬가지이다.
Hole
을 로드한다.Hole
이면 에러를 Throw 한다 (0이라는 정보를 같이 던진다 아래 참조).… 아래 생략. 왜 저렇게 바이트 코드가 생성되는지에 대해서는 잘 모르겠다. 아무래도 런타임에 타입이 바뀌는 자바스크립트의 특성 때문이라고 추정.
바이트 코드 변환 결과 전체를 보면 Constant pool
에 식별자 이름이 string
으로 저장되어 있다. 그것을 의미.
[generated bytecode for function: test (0x35810c611031 <SharedFunctionInfo test>)]
Bytecode length: 16
Parameter count 1
Register count 2
Frame size 16
OSR urgency: 0
Bytecode age: 0
0x35810c611a68 @ 0 : 10 LdaTheHole
0x35810c611a69 @ 1 : c4 Star0
26 S> 0x35810c611a6a @ 2 : 0d 01 LdaSmi [1]
0x35810c611a6c @ 4 : c3 Star1
0x35810c611a6d @ 5 : 0b fa Ldar r0
28 E> 0x35810c611a6f @ 7 : aa 00 ThrowReferenceErrorIfHole [0]
0x35810c611a71 @ 9 : 19 f9 fa Mov r1, r0
41 S> 0x35810c611a74 @ 12 : 0e LdaUndefined
0x35810c611a75 @ 13 : c4 Star0
0x35810c611a76 @ 14 : 0e LdaUndefined
44 S> 0x35810c611a77 @ 15 : a9 Return
Constant pool (size = 1)
0x35810c611a19: [FixedArray] in OldSpace
- map: 0x23c01ce012e1 <Map>
- length: 1
0: 0x09b1cacda561 <String[1]: #x>
Handler Table (size = 0)
Source Position Table (size = 10)
0x35810c611a79 <ByteArray[10]>
호이스팅이 잘 일어나긴 하며, Hole
이라는 값으로 초기화한다.