변수를 선언하려면 var
, let
, const
키워드가 필요하다. 변수를 선언한다는 공통점이 있지만, 서로 다른 특징을 가지고 있다.
개발자라면 필수적으로 알아야 할 var
, let
, const
의 차이점을 자세히 다루어보려 한다.
세가지 키워드를 알아보기 전, 변수 선언 시 변수 선언을 하면 어떤 단계를 거치는지 알아보자.
var member;
var member;
console.log(member); // undefined
// 어떠한 값도 할당하지 않았지만 undefined가 자동으로 할당되었다.
만약 초기화 단계를 거치지 않는다면 메모리 공간에는 이전에 사용했던 값이 남아있을 수 있는데, 이 값을 쓰레기 값이라고 한다. 값을 할당하지 않은 상태에서 곧바로 변수 값을 참조하려면 쓰레기 값이 나올 수 있기 때문에 초기화가 필요하다.
선언 단계와 초기화 단계가 동시에 진행된다.
선언 단계와 초기화 단계가 분리되어 진행된다. 런타임 이전에 자바스크립트 엔진에 의해 선언단계가 먼저 실행되고, 변수 선언문에 도달했을 때 초기화 단계가 실행된다.
만약 초기화 단계가 실행되기 전에 변수에 접근하려 하면 ReferenceError가 발생한다.
// 런타임 이전에 선언 단계 실행
console.log(user); // ReferenceError: user is not defined
let user; // 변수 선언문에서 초기화 단계 실행
console.log(user);
user = 1; // 할당문에서 할당 단계 실행
console.log(user); // 1
let 키워드로 선언한 변수는 스코프의 시작 지점부터 변수 선언문 지점까지 변수를 참조할 수 없다. 변수를 참조할 수 없는 구간을 일시적 사각지대(TDZ, Temporal Dead Zone)이라 부른다.
const 키워드는 선언+초기화+할당 단계가 동시에 일어난다. 따라서 반드시 선언과 동시에 할당이 이루어져야 한다.
const customer; // SyntaxError: Missing initializer in const declaration
변수 호이스팅이란, 변수 선언 위치와 상관없이 코드의 최상단으로 끌어 올려진 것처럼 동작하는 현상을 말한다.
변수 선언이 한 줄씩 순차적으로 실행되는 것이 아닌, 런타임 이전 단계에서 먼저 실행되는 변수 호이스팅이 발생한다.
console.log(member); //undefined
var member; // 변수 선언문
→ 코드가 순차적으로 실행된다면 console.log(member);
가 실행될 때 ReferenceError가 발생해야 하지만, undefined가 출력된다. 런타임 이전 단계에서 먼저 실행되기 때문이다.
let 키워드로 선언한 변수는 일시적 사각지대에서는 변수를 참조할 수 없기 때문에 변수 호이스팅이 발생하지 않는 것처럼 보이지만, 사실 호이스팅이 발생한다.
let user = 1; // 전역 변수
{
console.log(user); // ReferenceError: Cannot access 'user' before initialization
let user = 2; // 지역 변수
}
→ 만약 호이스팅이 발생하지 않는다면, 코드가 순차적으로 실행되어 전역변수 user의 값을 출력해야 한다. 하지만 호이스팅이 일어나기 때문에 ReferenceError가 발생하는 것이다.
const 키워드로 선언한 변수는 let 키워드로 선언한 변수처럼 변수 호이스팅이 발생하지 않는 것처럼 동작하지만, 실제로 호이스팅이 발생한다.
const customer = 1; // 전역변수
{
console.log(customer); // ReferenceError: Cannot access 'customer' before initialization
const customer = 2; // 지역변수
}
스코프는 식별자(변수 이름, 함수 이름, 클래스 이름 등)가 유효한 범위를 말한다. 코드의 가장 바깥 영역인 전역에서 선언된 변수는 전역 스코프를 갖는 전역 변수이고, 함수 몸체 내부인 지역에서 선언된 변수는 지역 스코프를 갖는 지역 변수이다.
모든 코드 블록이 지역 스포크를 만드는 특성을 블록 레벨 스코프라 하고, 함수의 코드 블록만을 지역 스코프로 인정하는 특성을 함수 레벨 스코프라고 한다.
var 키워드로 선언한 변수는 함수 레벨 스코프를 따른다. 따라서 함수 외부에서 var 키워드로 선언한 변수는 코드 블록 내에서 선언해도 모두 전역변수가 된다. 블록 밖에서 접근이 가능하다.
var x = 10;
if(true) {
var x = 100; // 전역 변수. x변수 중복 선언됨
}
console.log(x); // 100
let 키워드로 선언한 변수는 블록 레벨 스코프를 따른다. 따라서 블록 내에서만 접근이 가능하다.
let x = 10; // 전역 변수
if(true) {
let x = 100; // 지역 변수
}
console.log(x); // 10
const 키워드로 선언한 변수는 let 키워드로 선언한 변수와 마찬가지로 블록 레벨 스코프를 따른다.
{
const x = 100;
console.log(x); // 100
}
console.log(x); // ReferenceError: x is not defined
재할당이란 이미 값이 할당되어 있는 변수에 새로운 값을 또다시 할당하는 것을 말한다.
var 키워드로 선언한 변수는 값을 재할당할 수 있다.
var member = 'kim';
member = 'park';
var 키워드로 선언한 변수는 선언과 동시에 undefined로 초기화되기 때문에 엄밀히 말하면 변수에 처음으로 할당하는 것도 사실은 재할당이다.
→ 이전 값이 저장되어 있던 메모리 공간을 지우고 재할당 값을 새로 저장하는 것이 아니라, 새로운 메모리 공간을 확보하고 그 메모리 공간에 새로운 값을 저장하는 것이다.
let 키워드로 선언한 변수도 값을 재할당할 수 있다.
let user = 'kim';
user = 'park';
const 키워드로 선언한 변수는 재할당이 금지된다. const로 선언한 변수를 상수(constant)라고 한다.
const customer = 'kim';
customer = 'park'; // TypeError: Assignment to constant variable.
참고
모던 자바스크립트 Deep Dive (도서)
https://ko.javascript.info/variables