(JavaScript) var, let, const의 차이점

이전 글에서 자바스크립트 스코프에 대해서 알아보았는데요.

(JavaScript) 스코프(Scope)란?

ES6(ES2015)이전에는 변수를 선언할 수 있는 키워드가 var뿐이었습니다. 하지만 ES6에서는 let, const 키워드가 추가되어 이를 이용해서도 변수를 선언할 수 있게 되었습니다. 그럼 var, let, const의 차이점에 대해 알아보겠습니다.

var, let, const의 차이점
1. var는 함수 레벨 스코프이고 let, const는 블럭 레벨 스코프입니다.
2. var로 선언한 변수는 선언 전에 사용해도 에러가 나지 않지만 let, const는 에러가 발생합니다.
3. var는 이미 선언되어있는 이름과 같은 이름으로 변수를 또 선언해도 에러가 나지 않지만 let, const는 이미 존재하는 변수와 같은 이름의 변수를 또 선언하면 에러가 납니다.
4. var, let은 변수 선언시 초기 값을 주지 않아도 되지만 const는 반드시 초기값을 할당해야 합니다.
5. var, let은 값을 다시 할당할 수 있지만 const는 한번 할당한 값은 변경할 수 없습니다(단, 객체 안에 프로퍼티가 변경되는 것까지 막지는 못합니다).

2번 차이점의 경우를 보시면 ‘그럼 var는 호이스팅이 되고 let, const는 호이스팅이 안되기 때문에 그러는건가?’ 라고 생각하실 수 있는데요. 그렇지는 않습니다. 자바스크립트에서 사용하는 var, let, const, function, class 등등의 선언 키워드들은 모두 호이스팅이 되는데요.

var의 경우 호이스팅되면서 초기 값이 없으면 자동으로 undefined를 초기값으로 하여 메모리를 할당합니다. 그래서 var의 경우 선언 전에 해당 변수를 사용하려고 해도 메모리에 해당 변수가 존재하기 때문에 에러가 발생하지 않습니다.

console.log(num); // undefined
var num;

그런데 let, const의 경우 호이스팅이 되면서 초기 값이 없다면 var처럼 자동으로 초기값을 할당하지 않습니다(const의 경우 선언시 초기값을 할당하지 않으면 문법 에러가 납니다). 그래서 값이 할당되기 전까지 메모리를 할당하지 않기 때문에 선언전에(정확히는 값이 할당되기 전에) 사용하려고 하면 메모리에 해당 변수가 존재하지 않아서 에러를 발생시킵니다. 이처럼 변수가 선언되고 해당 변수에 값이 할당되기 전까지를 TDZ(Temporal Dead Zone)라고 합니다.

console.log(num); // Uncaught ReferenceError: num is not defined
let num = 1;
console.log(num); // 1
// 호이스팅 되었을 때
let num;
console.log(num); // 값이 할당되기 전이므로 아직 num은 메모리에 존재하지 않음. TDZ.
num = 1;
console.log(num); // 1

5번 차이점의 경우 const로 선언한 변수에 객체를 할당했을 때 const 변수가 가리키고 있는 객체 자체를 변경하는 것은 불가능하지만 해당 객체 내의 프로퍼티가 변경되는 것까지 막는다는 것은 아닙니다. 아래의 예제 코드를 한번 같이 보겠습니다.

const obj = { first: 1 };
// 에러 발생
obj = 1; // Uncaught TypeError: Assignment to constant variable.
// 에러 발생하지 않음.
obj.first = 2;
obj.second = 2;
delete obj.first;

위와 같이 const 변수가 가리키는 값 자체를 변경하려고 하면 에러가 발생하지만 객체 내의 프로퍼티의 추가, 변경, 삭제를 하는 것은 문제가 없습니다. 만약 객체의 프로퍼티도 변경되지 않게 객체를 선언하고 싶으시다면 Object.freeze() 메소드를 사용할 수 있습니다(Object.freeze()는 얕은 동결이기 때문에 객체 안에 있는 또다른 객체의 프로퍼티 변경까지 동결하지는 못합니다).


이렇게 var, let, const의 차이점에 대해 알아보았습니다.

var의 경우 버그 발생과 메모리 누수의 위험 등이 있기 때문에 var말고 let, const를 사용하시는 것이 좋습니다.