scope : 변수를 참조할 수 있는 범위
let은 변수간 선언된 블록, 구문 또는 표현식 내에서만 유효한 변수를 선언합니다.
var은 블록 범위를 무시하고 전역 변수나 함수 지역 변수로 선언됩니다.
//counter가 전역변수로 선언된다.
var counter;
//함수 안에 선언되었을 때 바깥에서 counter 변수를 하용할 수 없다.
function increase() {
var counter = 10;
}
블록 레벨 스코프는 모든 코드 블록(함수, if, for, while, try/catch) 내에서 선언된 변수는 코드 블록 내에서만 유효하며 코드 블록 외부에서 참조할 수 없습니다.
{
let x = 2;
}
console.log(x);
ReferenceError: y is not defined
let키워드로 선언한 변수는 블록 레벨 스코프이기 때문에 if문을 벗어나면 if문 안에서 선언된 변수 x에 대해 참조할 수 없습니다.
for문 또한 함수는 아니지만 블록 레벨이기 때문에 var과 let키워드를 사용할 때 다음과 같은 차이점이 있습니다.
for(var i = 1 ; i < 5 ; i++) {
console.log(i);
}
console.log(i);
1 2 3 4 5
for(let i = 1 ; i < 5 ; i++) {
console.log(i);
}
console.log(i);
1 2 3 4 "ReferenceError: i is not defined"
var키워드로는 동일한 이름을 갖는 변수를 중복 선언할 수 있습니다.
let키워드로는 중복 선언할 경우 Syntax Error가 발생합니다.
Hoisting : 모든 선언문(변수, 함수 등)이 스코프의 선두로 옮겨진 것 처럼 작동하는 특성입니다.
Hoisting 예시
console.log(foo);
var foo = 123;
위의 코드는 다음과 같이 작동됩니다.
var foo;
console.log(foo);
foo = 123;
undefined
console.log(x);
var x;
console.log(x);
x = 2;
console.log(x);
undefined
undefined
2
let의 선언단계와 초기화 단계 사이에 TDZ(Temporal Dead Zone)이 형성된다.
let키워드도 다음과 같이 호이스팅이 되긴 합니다.
//뒤 늦게 let 변수를 선언할 경우
(function() {
console.log(x);
let x = 5;
}());
"ReferenceError: Cannot access 'x' before initialization"
//아예 변수를 선언하지 않았을 경우
(function() {
console.log(x);
}());
"ReferenceError: x is not defined"