var, let, const의 차이점은 중복 선언, 재할당, 스코프, 전역 객체 프로퍼티, 호이스팅으로 크게 5가지로 나눌 수 있습니다.
1. 중복 선언 가능 여부
var : 변수의 중복 선언이 가능
var로 선언한 변수는 중복 선언이 가능합니다. 중복 선언 시 가장 나중에 할당된 값이 변수에 저장됩니다.
var name = 'kevin';
console.log(name); // name
var name = 'matt';
console.log(name); // matt
=> var를 사용할 경우 이미 사용하는 변수를 중복 선언하여 기존 값을 변경하게 되는 실수가 발생할 수 있습니다.
let, const : 변수의 중복 선언이 불가능
let과 const로 선언한 변수는 중복 선언이 불가능합니다. 중복 선언이 발생할 경우 에러가 발생합니다.
let name = 'kevin';
let name = 'matt'; // SyntaxError: Identifier 'name' has already been declared
const name = 'kevin';
const name = 'matt'; // SyntaxError: Identifier 'name' has already been declared
2. 재할당 가능 여부
var, let : 재할당이 가능
var, let으로 선언한 변수는 재할당이 가능합니다. 재할당 시 가장 나중에 할당된 값이 변수에 저장됩니다.
var a = 'kevin';
a = 'matt';
console.log(a); // matt
let b = 'matt';
b = 'kevin';
console.log(b); // kevin
const : 재할당이 불가능
const로 선언한 변수는 재할당이 불가능합니다. 재할당이 발생할 경우 에러가 발생합니다.
const name = 'kevin';
name = 'matt'; // TypeError: Assignment to constant variable.
3. 스코프
var : 함수 레벨 스코프
var는 함수 내부에서 선언된 변수만 지역 변수 취급됩니다.
var name = 'matt';
function foo () {
var name = 'kevin';
console.log(name);
}
foo(); // kevin
if (true) {
console.log(name); // matt
name = 'hello';
}
console.log(name); // hello
let, const : 블록 레벨 스코프
let, const는 코드 블록에서 선언된 변수는 지역 변수 취급됩니다.
if (true) {
let a = 'matt';
console.log(a); // matt
}
console.log(a); // ReferenceError: a is not defined
function foo () {
let b = 'kevin';
console.log(b);
}
foo(); // kevin;
console.log(b); // ReferenceError: b is not defined
4. 전역객체 프로퍼티
var : var로 선언된 변수는 전역객체 프로퍼티입니다.
var name = 'kevin';
console.log(window.name); // kevin
console.log(name); // kevin
let, const : let과 const로 선언된 변수는 전역객체 프로퍼티가 아닌 전역 렉시컬 환경의 선언적 환경 레코드 내에 존재합니다.
let name = 'kevin';
console.log(window.name); // undefined
console.log(name); // 'kevin'
5. 호이스팅
변수 선언은 자바스크립트 런타임에 앞서 먼저 소스코드의 평가 과정을 거치는데, 이때 변수 선언을 포함한 모든 선언문(ex. 변수 선언문, 함수 선언문 등)을 찾아내 먼저 실행합니다. 즉, 변수 선언이 어디에 있든 상관없이 다른 코드보다 먼저 실행되는 특징을 호이스팅(hoisting)이라 합니다.
변수 선언뿐만 아니라, var, let, const, function, class 키워드를 사용해 선언한 모든 식별자(변수, 함수, 클래스 등)는 호이스팅이 됩니다.
따라서, var, let, const 모두 호이스팅이 발생하지만 실제 동작하는 방식의 차이가 있습니다.
변수 선언은 '선언 → 초기화' 단계를 거쳐 수행됩니다.
- 선언 단계: 변수명을 등록하여 자바스크립트 엔진에 변수의 존재를 알림
- 초기화 단계: 값을 저장하기 위한 메모리 공간을 확보하고 암묵적으로 undefined를 할당해 초기화
var
var 키워드를 이용한 변수는 선언 단계와 초기화 단계가 동시에 진행됩니다. 즉, 런타임 이전에 자바스크립트 엔진에 의해 암묵적으로 선언 단계와 초기화 단계가 한 번에 진행됩니다.
console.log(name); // undefined
let name = 'kevin';
let
let 키워드를 이용한 변수는 선언 단계와 초기화 단계가 분리되어 진행됩니다. 런타임 이전에 자바스크립트 엔진에 의해 선언 단계가 먼저 실행되지만, 초기화 단계가 실행되지 않았기 때문에 해당 변수에 접근하려고 하면 참조 에러가 발생합니다. 초기화 단계는 코드 실행 과정에서 변수 선언문에 도달했을 때 수행됩니다.
console.log(name); // ReferenceError: name is not defined;
let name = 'kevin';
const
const 키워드를 이용한 변수는 선언 단계와 초기화 단계가 분리되어 진행됩니다. const 역시 런타임 이전에 선언 단계가 실행되고 변수 선언문에 도달했을 때 초기화 단계가 실행됩니다. 따라서, 다음의 경우는 초기화 단계가 진행되지 않은 상태이기 때문에 'Cannot access 'name' before initialization' 에러가 발생합니다. const 키워드로 선언한 변수는 선언문과 할당문을 한 번에 작성해야 합니다.
console.log(name); // ReferenceError: Cannot access 'name' before initialization
const name = 'kevin';
실제로 확인해 보면 let, const는 호이스팅이 안돼는 것 처럼 보이지만 호이스팅이 됩니다.
let a = 10;
if (true) {
console.log(a); // ReferenceError: Cannot access 'a' before initialization
let a = 20;
}
console.log(a); // 10
이러한 특징으로 let, const 키워드로 선언한 변수는 스코프의 시작 지점부터 초기화 단계 시작 지점까지 변수를 참조할 수 없는 일시적 사각지대(Temporal Dead Zone: TDZ) 구간이 존재합니다.
'프로그래밍 공부 > Javascript' 카테고리의 다른 글
브라우저에서 URL을 입력하고 요청한 페이지를 볼 때까지의 과정 (0) | 2022.02.16 |
---|---|
자바스크립트에서 변수를 선언하고 할당하는 일련의 과정 (0) | 2022.02.09 |
[자바스크립트] 이벤트 리스너 사용 시 this 바인딩 문제 (0) | 2021.11.19 |
[JS/Node.js] Callback, Promise, async/await / TIL 28일차 (0) | 2021.10.16 |
[JS/Node] 자바스크립트 비동기 / TIL 26 ~ 27일차 (0) | 2021.10.14 |