본문 바로가기

소프트웨어/Javascript

[JavaScript/ES6] var / let / const 의 차이점

 

Free code camp Var, Let, and Const – What's the Difference?을 참고하여 작성하였습니다.

 

 

tl;dr

var대신 letconst를 사용해라.

 

 

 

들어가기전에

ES2015 (ES6)에는 여러 신규 기능들이 선보였습니다. 2020년 현재에 이르러서 JavaScript 개발자들은 ES6를 사용하는데 많이 익숙지고 있으나 여전히 몇 가지 기능은 혼동을 주고 있습니다.

 

 

그 중 하나가 바로 letconst입니다. 기존에 사용하던 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이므로 hibye로 재선언됩니다. 물론 hi변수가 재선언 된다는 것을 확실하게 알고 있다면 문제가 되지 않을 수 있지만, hi변수가 이미 정의되었다는 것을 몰랐다면 문제가 발생할 수 있습니다.

hi변수를 다른 부분에서 사용한다면 원치 않은 결과를 볼 수 있으며 이것은 버그로 발전될 가능성이 있다는 것 입니다. 이러한 문제점 때문에 letconst가 필요한 것이죠.

 

 

 

 

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)

varlet은 최상위로 호이스팅(Hoisting)됩니다. 단, varundefined로 초기화된 것과는 달리 let초기화 되지 않습니다. 그러므로 let변수 선언 전에 해당 변수를 접근하려면 Reference Error오류가 발생하게 됩니다.

 

 

 

Const

const로 선언된 변수는 상수(변하지않음)입니다. constlet선언과 유사하게 동작합니다.

 

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선언은 전역 범위이거나 함수범위이고 letconst는 블록 범위이다.
  • var변수는 재할당, 재선언이 가능하다. let변수는 재할당은 가능하나 재선언은 할 수 없다. const변수는 재할당 및 재선언을 할 수 없다.
  • var, let, const모두 최상위로 호이스팅(Hoisting)된다. 단, var변수는 undefined로 초기화되는 반면 let, const변수는 초기화하지 않는다.
  • varlet은 초기화 없이 선언이 가능하지만 const는 선언과 동시에 초기화를 해주어야한다.