var, let, const
는 변수를 정의하는 키워드로, ES6 이전에는 var만 쓰였으나 ES6부터 let과 const가 추가되었습니다. 각 키워드의 특징들을 정리해보고 var 보다 let과 const의 사용을 권장하는 이유를 알아보겠습니다.
변수는 값을 담기 위한 공간입니다. ES6(ES2015) 이전에는 다음과 같은 방법으로 변수를 선언했습니다.
var id;
ES6 이후에는 두 가지 키워드(let, const)가 더 추가되었습니다.
let id;
const id;
변수에 데이터를 할당하는 방법은 다음과 같습니다.
var id = 2023;
let id = 2023;
const id = 2023;
변수 이름에는 몇가지 규칙들이 있습니다.
var 키워드로 선언된 변수는 재선언이 가능합니다.
var name = "홍길동";
var name = "홍길순";
var 키워드로 선언된 변수는 데이터의 재할당이 가능합니다.
var name = "홍길동";
name = "홍길순";
var 키워드로 선언된 변수는 함수 스코프
에 종속됩니다. 함수가 실행될 때 변수가 메모리에 할당되고, 함수가 끝나면 메모리에서 삭제됩니다.
function test(){
var name = "홍길동";
console.log(name);
}
test(); // 홍길동
console.log(name); // undefined
반면 블록 스코프
(중괄호 범위) 내에서 var 키워드로 변수로 선언하면 루프 밖에서도 사용할 수 있습니다.
var name = "홍길동";
if(name === "홍길동"){
var name = "홍길순";
console.log(name); //홍길순
}
console.log(name); //홍길순
let 키워드로 선언된 변수는 재선언이 불가능 합니다.
let name = "홍길동";
let name = "홍길순"; //error
let 키워드로 선언된 변수는 데이터의 재할당이 가능 합니다.
let name = "홍길동";
name = "홍길순";
let 키워드로 선언된 변수는 블록 스코프
로 종속됩니다. 변수가 선언된 블록과 그 하위 블록 내에서만 사용할 수 있습니다.
let name = "홍길동";
if(name === "홍길동"){
let name = "홍길순";
console.log(name); //홍길순
}
console.log(name); //홍길동
const 키워드로 선언된 변수는 재선언이 불가능 합니다.
const name = "홍길동";
const name = "홍길순"; //error
const 키워드로 선언된 변수는 데이터의 재할당이 불가능 합니다.
const name = "홍길동";
name = "홍길순"; //error
const 키워드로 선언된 변수는 블록 스코프
로 종속됩니다. 변수가 선언된 블록과 그 하위 블록 내에서만 사용할 수 있습니다.
호이스팅이란, 자바스크립트 코드가 실행되기 전 선언된 함수명, 변수명, 매개변수명을 모두 수집하여 해당 스코프 최상단으로 끌어올리는 것입니다. var, let, const는 모두 호이스팅의 대상이 됩니다. 자바스크립트 엔진은 코드를 실행하기도 전에 모든 변수명을 다 알게되는 셈입니다. 변수를 호이스팅 할 때는 변수명만 끌어올리고 값을 할당하는 과정은 원래 그자리에 남겨둡니다.
function fn (x) { //수집 대상 1(매개변수)
console.log(x);
var x; //수집 대상 2(변수)
console.log(x);
var x = 2; //수집 대상 3(변수)
console.log(x);
}
fn(1);
예상으로는 console log에 1, undefined, 2가 찍힐 것 같습니다.
다음은 호이스팅을 끝낸 코드입니다.
function fn (x) {
var x; //수집 대상 1의 선언 부분
var x; //수집 대상 2의 선언 부분
var x; //수집 대상 3의 선언 부분
x = 1; //수집 대상 1의 할당 부분
console.log(x); //1
console.log(x); //1
x = 2; //수집 대상 3의 할당 부분
console.log(x); //2
}
fn(1);
실제로는 1, 1, 2가 찍히는 걸 알 수 있습니다.
그럼 이미 선언된 변수들이니 실제 코드상의 위치보다 먼저 사용할 수 있을까요?
var와 let의 큰 차이점은 초기화 전에 접근할 수 있다는 점에 있습니다. 초기화란 값을 처음 할당받는 시점을 의미합니다. var는 초기화하기 전에 접근하면 undefined의 값을 가지게 됩니다. 반면 let은 초기화 하기 전까지 TDZ에 있게됩니다. 이때 let에 접근하면 오류가 발생합니다. const도 마찬가지 입니다.
console.log(name); // undefined
var name = "홍길동";
console.log(name); // error
let name = "홍길동";
예전부터 사용해오던 var를 놔두고 let과 const가 새로생긴 이유는 무엇일까요? 그 이유는 위에서 지금까지 정리해왔던 var와 let,const의 특징들을 통해 알 수 있습니다.
호이스팅으로 인해 변수의 선언 부분이 최상단으로 끌어올려집니다. 이때 var로 정의한 변수는 값을 초기화하기 전에도 접근이 가능하고, undefined값을 가지고 있습니다.
var로 선언된 변수는 함수 스코프를 가집니다. 함수 스코프는 블록 스코프와는 다르게, 중괄호({})로 둘러싸인 블록 밖에서도 변수가 유효합니다.
따라서 코드가 복잡해질 경우 변수가 어디에서 선언되었는지 추적하기 어려워지며, 블록 스코프를 무시하기 때문에 변수 누출의 위험도 있습니다. 이러한 이유로 ES6에서는 let과 const가 도입되었는데, 이들은 블록 스코프를 준수하고 호이스팅 문제를 완화하는 역할을 합니다.