var
var name = 'javascript';
console.log(name); // javascript
var name = 'react';
console.log(name); // react
var
로 선언한 변수는 동일한 이름으로 여러 번 중복해서 선언이 가능하다. 이와 같은 경우, 마지막에 할당된 값이 변수에 저장된다. 위의 예제를 보면 에러 없이 각기 다른 값이 출력되는 것을 볼 수 있다.
이는 필요할 때마다 변수를 유연하게 스용할 수 있다는 장점이 될 수도 있지만, 기존에 선언해둔 변수의 존재를 잊고 값을 재할당하는 등의 실수가 발생할 가능성이 크다. 특히 코드량이 많아졌을 때, 같은 이름의 변수명이 여러 번 선언되었다면 어디 부분에서 문제가 발생하는지 파악하기 힘들고 값이 바뀔 우려가 있다.
이를 보완하기 위해 ES6부터 추가된 변수 선언 방식이 let
과 const
이다.
let
let name = 'javascript';
console.log(name); // javascript
let name = 'react';
console.log(name);
// Uncaught SyntaxError: Identifier 'name' has already been declared
name = 'vue';
console.log(name); // vue
var
과 다르게 let
은 해당 변수가 이미 선언되었다는 에러 메시지가 출력된다. 이처럼 중복 선언이 불가능하다.
name = 'vue'
와 같이 변수 선언 및 초기화 이후 반복해서 다른 값을 재할당 할 수는 있다.
const
const name = 'javascript';
console.log(name); // javascript
const name = 'react';
console.log(name);
// Uncaught SyntaxError: Identifier 'name' has already been declared
name = 'vue';
console.log(name);
// Uncaught TypeError: Assignment to constant variable
let
과 const
의 차이점은 immutable
의 여부이다. let
은 변수에 다른 값을 재할당할 수 있지만, const
는 재할당 시 에러 메시지가 출력된다. function func() {
const list = ["A", "B", "C"]
list = "D";
console.log(list);
// TypeError: Assignment to constant variable
list.push("D");
console.log(list); // ["A", "B", "C", "D"]
}
이처럼 const
는 constant(상수)를 뜻하기 때문에 한 번만 선언이 가능하며 값을 바꿀 수도 없다. 하지만 위 예제와 같이 배열과 오브젝트의 값을 변경하는 것은 가능하다.
결과적으로 const
는 불변을 의미하는 것과 다르게, 값을 재할당하는 코드만 불가능하다고 볼 수 있다.
const
를 기본으로 사용하여 불필요한 변수의 재사용을 방지하고, 재할당이 필요한 경우 let
을 사용하는 것이 좋다.
스코프란 유효한 참조 범위를 뜻하며, 기본의 방법인 var
로 선언한 변수와 let
또는 const
로 선언한 변수의 스코프는 다르다.
var
function func() {
if (true) {
var a = 5;
console.log(a); // 5
}
console.log(a); // 5
}
func(); // 5
console.log(a); // ReferenceError: a is not defined
let, const
function func() {
if (true) {
let a = 5;
console.log(a); // 5
}
console.log(a); // ReferenceError: a is not defined
}
console.log(a); // ReferenceError: a is not defined
var
/* 변수 호이스팅 */
console.log(a); // undefined
var a = 5;
console.log(a); // 5
/*
foo(); // foo
function foo() {
console.log("foo");
}
a
가 선언되기 저에 참조되었음에도 에러가 발생하지 않는다. 이는 코드 실행 전에 자바스크립트 내부에서 미리 변수를 선언하고 undefined
로 초기화를 해두었기 때문이다. 함수 선언문 또한 동일하게 선언되기 전 호출됨에도 에러가 발생하지 않는다.let, const
/* 변수 호이스팅 */
console.log(a); // ReferenceError: a is not defined
let a = 5;
console.log(a); // 5
/* 함수 호이스팅 */
foo(); // error
var foo = function() {
console.log("foo");
}
변수 a
가 선언되기 전에 참조하기 때문에 에러가 발생한다. 이는 호이스팅이 발생하지 않는 것이 아니라, 변수의 선언과 초기화 사이에 일시적으로 변수 값을 참조할 수 없는 구간인 TDZ(Temporal Dead Zone)에 빠졌기 때문에 보이는 현상이다.
함수 표현식을 사용하거나 let
또는 const
로 변수를 선언하는 경우, 자바스크립트 내부에서는 코드 실행 전 변수 선언만 해둘뿐 초기화는 코드 실행 과정에서 변수 선언문을 만났을 때 수행한다. 그렇기 때문에 호이스팅이 발생하기는 하지만, 값을 참조할 수 없기 때문에 동작하지 않는 것처럼 보이는 것이다.