
ES6(ECMAScript 2015) 이전까지 자바스크립트에서 변수를 선언할 수 있는 유일한 키워드는 var였다.
하지만 var는 독특한 스코프 규칙과 호이스팅 특성으로 인해 의도치 않은 버그를 자주 유발했다. (코로나같은 전염병)
이를 해결하기 위해 let과 const가 등장했다.(백신 등장)
var는 현대 자바스크립트 개발에서 사실상 쓰레기 패턴으로 간주된다.
이유는 아래와 같다.
undefined를 반환하여 코드의 흐름을 예측하기 어렵게 만든다.스코프는 식별자(변수, 함수 등)가 접근할 수 있는 범위를 의미한다.
var는 오로지 함수의 코드 블록만을 지역 스코프로 인정한다. if, for, while 등의 일반 코드 블록 안에서 선언하더라도 함수 내부가 아니라면 모두 전역 변수가 된다.
var x = 1;
if (true) {
// if문 블록 안이지만 함수가 아니므로 전역 변수 x를 중복 선언하고 덮어쓴다.
var x = 10;
}
console.log(x); // 10 (의도치 않은 값 변경)
for 문의 반복 변수(i) 역시 블록 밖으로 누출되어 바깥까지 오염시킨다.
var i = 10;
for (var i = 0; i < 5; i++) {
console.log(i); // 0 1 2 3 4
}
// for문 밖에서도 i가 살아있으며 값이 5로 덮어씌워진다.
console.log(i); // 5
let과 const는 함수뿐만 아니라 모든 중괄호 코드 블록({ ... })을 독립된 지역 스코프로 인정한다.
let foo = 1; // 전역 변수
{
let foo = 2; // 블록 내부의 지역 변수
let bar = 3; // 블록 내부의 지역 변수
}
console.log(foo); // 1 (외부 전역 변수는 안전하게 유지)
console.log(bar); // ReferenceError: bar is not defined
블록 내부에서 선언된 foo와 bar는 해당 블록이 끝나면 스코프가 종료되어 외부에서 접근할 수 없다.

두 키워드 모두 블록 레벨 스코프를 따르고 일시적 사각지대(TDZ, Temporal Dead Zone)로 인해 선언 전 참조 시 ReferenceError를 발생시킨다. 차이점은 재할당 가능 여부다. (DMZ아님)
let: 선언 후 값의 재할당이 가능하다. 반복문의 카운터 변수나 상태에 따라 값이 바뀌어야 하는 변수에 한해 제한적으로 사용한다.const: 선언과 동시에 반드시 초기화해야 하며, 이후 재할당이 금지된다.const로 선언된 객체(Object, Array) 자체의 메모리 주소(참조값)는 바꿀 수 없지만, 객체 내부의 프로퍼티나 배열 요소는 수정할 수 있다.{
// TDZ 구간: 선언 이전에 접근 시 에러 발생
// console.log(foo); // ReferenceError: Cannot access 'foo' before initialization
const foo = 1;
// foo = 2; // TypeError: Assignment to constant variable.
}
const를 사용한다. 재할당을 막아 불변성을 유지하고 코드의 안정성을 확보한다.let으로 좁혀서 사용한다. (스코프의 범위는 최대한 좁게 유지)var는 사용하지 않는다.참조 - 이웅모, 『모던 자바스크립트 Deep Dive 』, 위키북스(2020), p.208 ~ p.218.