Free code camp Var, Let, and Const – What's the Difference?을 참고하여 작성하였습니다.
tl;dr
var
대신 let
과 const
를 사용해라.
들어가기전에
ES2015 (ES6)에는 여러 신규 기능들이 선보였습니다. 2020년 현재에 이르러서 JavaScript 개발자들은 ES6를 사용하는데 많이 익숙지고 있으나 여전히 몇 가지 기능은 혼동을 주고 있습니다.
그 중 하나가 바로 let
과 const
입니다. 기존에 사용하던 var
에 비해 어떤 점에서 차이가 있는지 알아봅시다.
var
, let
, const
의 scope, 사용, 그리고 호이스팅(hoisting)의 관점으로 알아보겠습니다.
Var
ES6전에는 여러 이슈가 있었음에도 var
를 사용하였습니다. 이 때문에 새로운 방식의 변수 선언 방식이 등장하게 되었습니다. 무엇이 문제였는지를 알아보기 전에 var
의 특징을 알아보겠습니다.
Scope
는 해당 변수가 어디까지서 사용할 수 있는지를 의미합니다. var
선언은 전역(global) 범위나 함수(function)/지역(local) 범위를 가집니다.
var
변수가 함수 밖에서 선언될 경우에는 전역 범위입니다. 즉, var
변수가 함수 밖에서 선언될 경우 모든 window에서 접근이 가능합니다.
만약 var
변수가 함수 안에서 선언된다면 함수 범위로서 해당 함수 안에서만 접근이 가능합니다.
다음 예제를 살펴봅시다.
var hi = "hey hi";
function newFun() {
var hello = "hello";
}
여기서 변수 hi
는 함수 밖에서 선언되었으므로 전역 범위이며 hello
는 함수 범위입니다. 그래서 변수 hello
는 함수 밖에서 접근할 수 없습니다.
var hi = "hey hi";
function newFun() {
var hello = "hello";
}
console.log(hello); // Uncaught ReferenceError: hello is not defined
위와 같이 hello
를 호출하게 되면 함수 밖에서 접근할 수 없다는 오류 메시지가 발생합니다.
var는 재선언 및 재할당 가능
같은 범위내에서 var
변수는 재선언을 해도 오류가 발생하지 않습니다.
// 변수 재선언
var hi = "hi";
var hi = "bye";
// 변수 값 재할당
hi = "bye bye bye";
var의 호이스팅(Hoisting)
호이스팅(Hoisting)이란 JavaScript에서 변수나 함수의 정의 부분이 해당 범위의 최상위로 끌어올려지는(Hoisting)것을 의미합니다. 예를 들어 아래와 같이 코드를 썼을 경우
console.log(hi);
var hi = "hello";
JavaScript 엔진은 다음과 같이 코드를 해석합니다.
var hi;
console.log(hi); // undefined
hi = "hello"
즉 var
변수는 해당 범위의 가장 위로 끌어올려지고(Hoisted) undefined
로 초기화 됩니다.
var의 문제점
아래와 같이 코드를 구성 시 var
변수의 취약성이 발생할 수 있습니다.
var hi = "hello";
var condition = 4;
if(condition > 3) {
var hi = "bye";
}
console.log(hi); // "bye"
condition > 3
조건이 true이므로 hi
는 bye
로 재선언됩니다. 물론 hi
변수가 재선언 된다는 것을 확실하게 알고 있다면 문제가 되지 않을 수 있지만, hi
변수가 이미 정의되었다는 것을 몰랐다면 문제가 발생할 수 있습니다.
hi
변수를 다른 부분에서 사용한다면 원치 않은 결과를 볼 수 있으며 이것은 버그로 발전될 가능성이 있다는 것 입니다. 이러한 문제점 때문에 let
과 const
가 필요한 것이죠.
Let
따라서 변수를 선언할 때 let
을 사용하는 것이 권장됩니다. var
를 이용한 변수 선언에 대한 문제점을 개선하기 위한 것으로 어떻게 개선이 가능한지 하나씩 알아봅시다.
let은 블록(Block) 범위를 가집니다
블록(Block)은 중괄호{}
로 둘러쌓인 단위이며 여기서 나올 수 없습니다. 중괄호로 둘러싸인 곳은 블록입니다.
즉 블록안에 let
으로 선언된 변수는 블록 내에서만 사용할 수 있습니다. 아래의 예제를 살펴봅시다.
let condition = 4;
if (condition > 3) {
let hi = "bye";
console.log(hi); // "bye"
}
console.log(hi); // Uncaught ReferenceError: hi is not defined
hi
변수를 블록 내에서 정의되었고 이를 호출하려고 하면 오류가 발생합니다. let
변수는 블록 범위에만 유효하기 때문입니다.
let은 값의 재할당이 가능하나 재선언은 불가능
let
로 선언된 변수는 해당 범위 내에서는 var
로 선언된 변수처럼 값의 재할당이 가능합니다. 그러나 let
변수는 같은 범위 내에서 var
변수처럼 재선언을 할 수 없습니다.
아래처럼 let
으로 선언한 변수에는 값을 재할당 할 수 있습니다.
let hi = "hi"; // "hi"
hi = "bye"; // "bye"
그러나 같은 이름의 변수를 재선언하게 되면 오류가 발생합니다.
let hi = "hi";
let hi = "bye"; // SyntaxError: Identifier 'hi' has already been declared
범위(scope)가 다른 경우에는 let
으로 재선언을 해도 문제가 발생하지 않습니다.
let hi = "hi";
if (true) {
let hi = "hi in block";
console.log(hi); // "hi in block"
}
console.log(hi); // "hi"
위의 코드가 정상인 이유는 두 개의 hi
변수는 다른 범위이기 때문에 다른 변수로 취급하기 때문에 오류가 발생하지 않습니다.
이 때문에 var
보다 let
를 사용하는 것이 더 좋은 이유입니다. let
을 사용하면 중복된 이름을 사용하더라도 범위(Scope)가 다른 경우에는 명확하게 구분하여 사용할 수 있습니다.
또한 한 블록에 한번만 선언이 가능하기 때문에 var
변수에서 일어난 문제점이 발생하지도 않게 됩니다.
let의 호이스팅(Hoisting)
var
와 let
은 최상위로 호이스팅(Hoisting)됩니다. 단, var
는 undefined
로 초기화된 것과는 달리 let
초기화 되지 않습니다. 그러므로 let
변수 선언 전에 해당 변수를 접근하려면 Reference Error
오류가 발생하게 됩니다.
Const
const
로 선언된 변수는 상수(변하지않음)입니다. const
는 let
선언과 유사하게 동작합니다.
const는 블록(Block) 범위를 가집니다
let
처럼 const
은 같은 블록 내에서만 사용할 수 있습니다.
const는 재선언 및 값 재할당이 불가능
const
로 선언된 변수는 해당 블록 내에서는 항상 같은 값을 유지합니다. 재선언 및 값의 재할당이 불가능합니다. 따라서 const
로 선언한 경우에는 다음과 같이 사용할 수 없습니다.
const hi = "hi";
hi = "bye"'' // Uncaught TypeError: Assignment to constant variable.
const hi = "hi";
const hi = "bye"'' // SyntaxError: Identifier 'hi' has already been declared
따라서 const
변수 선언 시 초기화를 바로 해줘야합니다.
한편, const
로 선언된 변수 값에 object 객체가 할당될 경우에는 조금 다르게 취급해줘야합니다.
const hi = {
msg: "hi",
time: 4
}
hi = {
msg: "bye",
addr: "Seoul"
} // SyntaxError: Identifier 'hi' has already been declared
hi
변수는 const
로 선언되었기 때문에 다른 object 객체로 재할당 할 수 없습니다.
만약 hi
변수의 msg
속성값을 변경하고 싶을 경우에는 .
을 사용하여 프로퍼티에 접근합니다.
hi.msg = "bye";
const의 호이스팅(Hoisting)
let
처럼 const
는 최상위로 호이스팅되지만 초기화되지 않습니다.
정리
var
선언은 전역 범위이거나 함수범위이고let
과const
는 블록 범위이다.var
변수는 재할당, 재선언이 가능하다.let
변수는 재할당은 가능하나 재선언은 할 수 없다.const
변수는 재할당 및 재선언을 할 수 없다.var
,let
,const
모두 최상위로 호이스팅(Hoisting)된다. 단,var
변수는undefined
로 초기화되는 반면let
,const
변수는 초기화하지 않는다.var
와let
은 초기화 없이 선언이 가능하지만const
는 선언과 동시에 초기화를 해주어야한다.