function run() {
var foo = "Foo";
let bar = "Bar";
console.log(foo, bar);
{
// var foz = "Foz"
let baz = "Baz";
console.log(baz);
}
// console.log(foz); // "Foz"
console.log(baz); // ReferenceError: baz is not defined
}
따라서, 위 코드를 실행했을 때, 블록 안에 let
으로 선언한 baz
를 출력하면 ReferenceError가 발생하고, 반대로 var
으로 선언함 foz
를 출력하면 그대로 출력하는 것을 볼 수 있다.
function run() {
console.log(foo); // undefined
var foo = "Foo";
console.log(foo); // Foo
}
run();
따라서, var의 경우 var foo
가 함수 스코프의 최상단으로 호이스팅이 되서, 선언 전에 출력하면 undefined
가 출력이 된다.
function run() {
console.log(foo); // ReferenceError: Cannot access 'foo' before initialization
let foo = "Foo";
console.log(foo);
}
run()
반면에, let의 경우에는 let foo
가 선언 전에 호이스팅 되긴 하지만, 어떤 값도 가지지 않기 때문에 ReferenceError가 발생한다. 이런 현상을 TDZ(Temporal Dead Zone)이라고 한다. 즉, 선언은 되었지만, 참조는 할 수 없는 사각지대를 갖는다는 것이다.
'strict mode'가 아닐 때,
// 'use strict';
var foo = "Foo"; // globally scoped
let bar = "Bar"; // globally scoped
console.log(window.foo); // Foo
console.log(window.bar); // undefined
브라우저 환경에서 글로벌 객체는 window
인데, var의 경우 바인딩이 되었고, let의 경우에는 바인딩이 되지 않았다는 것을 볼 수 있다.
var foo = "foo1";
var foo = "foo2"; // 문제 없이 재선언 가능
let bar = "bar1";
let bar = "bar2"; // SyntaxError: Identifier 'bar' has already been declared