자바스크립트에서 사용되는 세 가지 변수들 var
, let
, const
의 차이점이 무엇인지 간단하게 정리해보자.
먼저 그 차이점을 이해할 때에 있어서 가장 중요한 두 가지 키워드는 Scope
와 Hoisting
이다.
변수가 선언되면 모든 코드에서 사용 가능한 것이 아니라 변수의 종류에 따라 사용 가능한 '유효 범위'가 정해지게 되는데 이를 Scope 스코프라 한다. 다시 말해, 스코프란 변수가 사용되는 유효 범위를 뜻한다. 종류는 크게 전역/ 지역 스코프로 나뉜다.
var global = 'global scope'; // 어떤 함수나 블록에도 속하지 않는다.
function foo() {
var local = 'local scope'; // 함수 내에 존재한다.
}
* global과 local은 상대적 개념이 아니다.
스코프에서 또 하나 중요한 점은 내부 스코프에서 외부 스코프로 접근은 가능하지만, 그 반대의 접근은 불가하다는 것이다.
var global = 'global scope';
function foo() {
var local = 'local scope';
console.log(global); // 'global scope'
console.log(local); // 'local scope'
}
foo();
console.log(global); // 'global scope'
console.log(local); // 외부에서 내부 스코프로 접근은 불가하다. Uncaught ReferenceError: local is not defined
스코프 내에서 모든 변수 선언들을 위치에 관계없이 스코프의 가장 최상단으로 끌어올려 선언시키는 것을 뜻한다.
function first() {}
function secone() {}
var third = 'hello';
const fourth = 'world';
이러한 순서의 코드라도 사실 내부적으로는 변수 '선언'들이 호이스팅되어 아래와 같은 코드로 작동한다.
var third;
const fourth;
function first() {}
function secone() {}
third = 'hello';
fourth = 'world';
*변수 할당, 재할당은 해당되지 않고 선언만을 Hoisting 호이스팅한다.
*내부적인 처리이므로 실제로 코드가 변경되어 쓰여지는 것은 아니다.
var
는 ES2015(ES6) 이전부터 사용되었고, let
과 const
는 ES6에서 등장했다. 이 세 가지는 scope
와 hoisting
을 중점으로 뚜렷한 차이가 나타난다.
var
- 함수 스코프를 사용하며 재할당, 재선언 모두 가능하다.
var testVar = 1;
console.log(testVar); // 1
testVar = 2;
console.log(testVar); // 2
var testVar = '1';
console.log(testVar); // '1'
- undefiend로 초기화되어 호이스팅된다.
console.log(testVar); // undefiend
var testVar = 1;
console.log(testVar); // 1
호이스팅시 undefiend로 값이 자동 초기화되는 var
와 달리 let
,const
는 초기 값이 설정되지 않는다. 따라서 let
과 const
의 경우 변수 값이 선언되고 난 후에야 실제 변수 사용이 가능하며 그 이전에는 ReferenceError를 발생시킨다. 이렇게 호이스팅 - 변수 선언 사이의 구간, 변수가 존재하기는 하나 선언되기 전까지의 구간을 Temporal Dead Zone
이라 일컫는다.
에러가 발생하기는 해도 let
과 const
역시 변수의 존재를 알기에 에러가 발생하는 것이므로 호이스팅이 되고 있는 것이다. 나아가 에러를 발생시킴으로써 이후 발생 할 버그를 초기에 잡을 수 있다.
console.log(testLet); // Uncaught ReferenceError: Cannot access 'testLet' before initialization
let testLet = 'test tdz';
console.log(testLet); // 'test tdz'
console.log(testConst); // Uncaught ReferenceError: Cannot access 'testConst' before initialization
const testConst = 'test tdz';
console.log(testConst); // 'test tdz'
let
- 블록 스코프를 사용하며 재할당이 가능하고 재선언은 불가하다.
let testLet = 1;
console.log(testLet); // 1
testVar = 2;
console.log(testLet); // 2
let testVar = '1';
console.log(testLet); // Uncaught SyntaxError: Identifier 'testVar' has already been declared
- 호이스팅이 되긴 하나 변수 값 선언 전까지 TDZ 제한으로 ReferenceError를 발생시킨다
console.log(testLet); // Uncaught ReferenceError: Cannot access 'testLet' before initialization
let testLet = 1;
console.log(testLet); // 1
const
- 블록 스코프를 사용하며 재선언, 재할당 모두 불가하다.
const testConst = 1;
console.log(testConst); // 1
testVar = 2;
console.log(testConst); // Uncaught TypeError: Assignment to constant variable.
const testVar = '1';
console.log(testConst); // Identifier 'testVar' has already been declared
- let
과 동일하게 호이스팅이 되긴 하나 변수 값 선언 전까지 TDZ 제한으로 ReferenceError를 발생시킨다
console.log(testConst); // Uncaught ReferenceError: Cannot access 'testConst' before initialization
const testConst = 1;
console.log(testConst); // 1