Javascript에선 3개의 변수가 있습니다. var, let, const로 각각의 특징과 차이점이 있는데, 스코프와 호이스팅을 기준으로 비교해보려고 합니다.
어디에 선언이 되어있든 간에 변수들은 어떠한 코드가 실행되기 전에 처리가 됩니다.
MDN 문서
javascript에서 오래 사용되어 왔던 변수문 입니다. variable에서 나온 단어입니다. 현재는 거의 사용되지 않고 있는데 여러 문제점을 야기할 수 있기 때문입니다. 특징은 다음과 같습니다.
var는 동일한 이름으로 계속 선언할 수 있습니다.
var x = 1;
console.log(x); // 1
var x = 'hello';
console.log(x); // hello
따라서 변수명을 고려할때 중복되지 않도록 확인해야합니다. 중복 선언을 하게 되면 기존 변수에 할당된 값이 변경될 수도 있고 logical error가 발생될 수도 있습니다. 여러 문제를 야기할 수 있기 때문에 var 사용시 신경써야 하는 항목이 늘어나게 됩니다.
javascript는 대부분의 언어처럼 코드의 작성순서대로 진행됩니다. 이때, 위에있는 코드가 아래에 있는 변수에 접근하면 에러가 발생하는데 var를 사용할 경우 에러가 발생하지 않고, undefined으로 값이 전달됩니다. 이는 var 변수가 호이스팅 되어 다른 코드보다 먼저 선언 되기 때문입니다. 하지만 할당은 할당이 작성된 순서에 진행되기 때문에 undefined이 됩니다.
function logg(tmp) {
console.log(tmp);
}
logg(x); // undefined
var x = 3;
logg(x); // 3
var는 함수 내부에서 선언된 변수는 다른 곳에서 사용할 수 없습니다. 그 외의 block문 에서는 전역 변수처럼 사용이 가능합니다.
//function 안에서 선언 했을 경우
function printVar() {
var y = 2;
console.log(y, ` in function`);
}
printVar() // 2 in function
console.log(y); // ReferenceError: y is not defined
//그 외 block문에서 선언 했을 경우
if(true) {
var z = 3;
console.log(z, ` in if`); // 3 in if;
}
console.log(z, `in global`); // 3 in global;
z = 5;
console.log(z, `in global`); // 5 in global;
let과 const변수는 ECMAScript6에서 처음 등장했습니다. var의 스코프 및 호이스팅 문제를 해결하기 위해 도입되었습니다. var와 다르게 중복선언이 불가하고, 블록 스코프를 가지며, 호이스팅 되지 않습니다.
let x = 10;
let x = 11; // SyntaxError: Identifier 'x' has already been declared
중복선언을 할 경우 error가 발생합니다. 재선언으로 인한 logical error를 방지 할 수 있습니다.
function logg(tmp) {
console.log(tmp);
}
logg(z); // ReferenceError: z is not defined
let z = 3;
var와 달리 먼저 선언되지 않은 변수는 접근할 수 없습니다. 코드가 진행하는 흐름대로 변수를 먼저 선언하고 함수에서 사용할 수 있습니다.
function printWord() {
let word = 'hello';
console.log(word); // hello
}
console.log(word); // ReferenceError: word is not defined
블록문 안에 있는 변수는 전역변수가 아니기 때문에 블록문 밖에서 사용할 수 없습니다. var의 경우 함수를 제외한 기타 블록문 안의 변수들도 전역변수처럼 이용했지만 let과 const는 불가능합니다. 따라서 변수명의 재사용도 가능합니다.
const와 let은 비슷한 특징을 가지고 있습니다. 다만 const의 경우 재할당이 불가능하다는 특징이 있습니다. 이 외의 특징은 let과 거의 동일합니다.
const key = 20;
key = 10; // TypeError: Assignment to constant variable.
let과 const의 scope 범위를 얘기하면 tdz(temporal dead zone)이라는 단어가 등장합니다. tdz란 변수의 선언과 초기화 사이에 발생하는 일시적인 접근 불가 공간을 말합니다. mdn문서 에선 일시적 사각지대 라는 단어로 번역되어 있습니다.
사각지대는 코드의 작성 순서(위치)가 아니라 코드의 실행 순서(시간)에 의해 형성되기 때문입니다.
MDN 문서 let-tdz
{
console.log(xx); // ReferenceError: Cannot access 'xx' before initialization
let xx = "tdz";
console.log(xx); // tdz
}
첫번째 console.log에서 xx 변수에 접근할때 사실 let xx는 선언되어있습니다. 스코프가 동작할때 제일 먼저 변수와 함수들이 선언 됩니다. 이때 var로 선언할 경우 undefined로 초기화가 되지만 let과 const는 초기화를 하지 않습니다. 따라서 let, const는 tdz에 위치하게 되고, 해당 변수에 접근을 하게 되면 ReferenceError가 발생합니다. 재할당이 불가능한 const는 초기화와 할당이 동시에 해야하기 때문에 let보다 조금 더 초기화 실수를 줄일 수 있습니다.
세 변수의 차이를 아래와 같이 정리할 수 있습니다.
| var | let | const | |
|---|---|---|---|
| 중복선언 | ✅ | ❌ | ❌ |
| 호이스팅 | ✅ | ❌ | ❌ |
| 재할당 | ✅ | ✅ | ❌ |
| 초기화 생략 | ✅ | ✅ | ❌ |
| scope | function | block | block |
mdn - var
mdn - let
mdn - const
https://velog.io/@hoo00nn/TDZ-Temporal-Dead-Zone-%EC%9D%B4%EB%9E%80