Javascript - var, let, const, Hoisting
var & let
JavaScript는 es6 문법 도입 이전까지 var 키워드만을 이용하여 변수를 선언했다. 그렇기 때문에 코드 실행 중 예기치 못한 문제들이 자주 발생하게 되었다. 예를 들면 다음과 같은 문제들이다.
var a = "a"
console.log(a) // "a"
var a = "b"
console.log(a) // "b"
같은 변수에 다른 값을 두 번 할당하였는데도 에러가 나지 않고 멀쩡히 다른 값이 출력되는 것을 볼 수 있다.
var는 변수의 재선언, 재할당 모두가 가능하기 때문에 유연한 변수 선언 면에서는 장점일 수 있으나, 코드양이 많아질수록 유지 관리가 힘들며 에러를 찾기도 힘들어진다.
또한 var는 Hoisting과도 연관이 있다.
호이스팅이란?
인터프리터가 변수와 함수의 메모리 공간을 선언 전에 미리 할당하는 것
var로 선언한 변수의 경우 호이스팅 시 undefined로 변수 초기화
반면 let과 const로 선언한 변수의 경우 호이스팅 시 변수초기화 x
console.log(a) // undefined
var a = "something"
console.log(b) // Error: Uncaught ReferenceError: b is not defined
let b = "something"
변수 생성 과정은 선언 단계 => 초기화 단계 => 할당 단계 이렇게 총 세 단계를 거쳐 생성되는데, var로 선언된 변수는 선언 단계에서 undefined를 할당하는 과정(초기화 과정)이 한 번에 진행되어서 변수 선언 전 호이스팅이 가능하지만, let은 선언 단계에서 초기화 과정(메모리 공간 확보)이 이루어지지 않기 때문에 선언 이전에 변수를 참조할 수 없다.
let
let은 변수의 재선언은 불가능하지만 재할당이 가능하다.
let variable = 'v'
console.log(variable) // 'v'
variable = 'c'
console.log(variable) // 'c'
이와 같이 변수에 다른 값을 재할당 하면 제대로 값을 출력하는 것을 확인할 수 있다.
또한, let은 변수를 선언할 시 할당을 반드시 하지 않아도 된다.
let bar;
console.log(bar) // undefined
bar = 'bar'
console.log(bar) // 'bar'
const
const는 변수의 재선언, 재할당 모두 불가능하다.
변수에 값을 한 번 할당하게 되면 바꿀 수 없기 때문에 변수를 선언할 시 할당이 반드시 이루어져야 한다.
const a = 1
a = 2 // TypeError: Assignment to constant variable.
const b // SyntaxError: Missing initializer in const declaration
예시와 같이 const로 선언한 변수는 값을 재할당할 수 없으며, 변수를 선언만 하는 것도 안된다.
간단 요약
var : 변수의 재선언/재할당 모두 가능, Hoisting이 되어 변수를 선언하기 전에 참조할 수 있다.
let: 변수의 재선언은 불가능하나 재할당은 가능, 변수를 선언하기 전에 참조할 수 없으나, 변수를 선언할 시 할당을 반드시 할 필요는 없다.
const: 변수의 재선언/재할당 모두 불가능, 변수를 선언하기 전에 참조할 수 없으며, 변수를 선언할 시 할당을 반드시 해야 한다.
var, let, const의 변수 선언, 초기화, 할당
1. var로 선언한 변수
- 선언 단계와 초기화 단계가 동시에 실행
- 즉, 변수가 선언되면 동시에 초기화가 이루어져 undefined가 할당된다.
- 따라서, 호이스팅으로 선언 단계가 이루어지고 동시에 초기화 단계도 이루어진다.
2. let으로 선언한 변수
- 선언 단계와 초기화 단계가 분리되어 실행
- 선언 단계 : 호이스팅으로 선언 단계가 먼저 이루어짐
- 초기화 단계 : 실제 코드에 도달했을 때 초기화 단계가 이루어진다.
console.log(b); // ❗️Uncaught ReferenceError: b is not defined
let b; // 초기화
console.log(b); // undefined
cf) let과 const는 TDZ의 영향을 받는데, 선언 단계와 초기화 단계 사이에서 변수를 참조할 경우 TDZ로 인해 레퍼런스 에러가 발생한다.
TDZ(일시적 사각지대): 변수의 선언부터 변수의 초기화가 이루어지기 전까지의 구간
3. const로 선언한 변수
- 선언, 초기화, 할당 단계가 동시에 이뤄짐
console.log(c); // ❗️ Uncaught ReferenceError: c is not defined
const c; // ❗️Uncaught SyntaxError: Missing initializer in const declaration
const c = 1; // 선언, 초기화, 할당
정리하자면,
var | 선언과 초기화 동시에 |
let | 선언과 초기화 분리 |
const | 선언, 초기화, 할당이 동시에 |