본문 바로가기
취준적인

var, let, const의 차이는 무엇일까?

by klm hyeon woo 2023. 2. 9.

var, let, const의 세가지 차이점

  1. var 선언은 전역 범위 또는 함수 범위이며, let과 const는 블록 범위({})이다.
  2. var 변수는 범위 내에서 업데이트 및 재선언이 가능하다. let 변수는 업데이트를 할 수 있지만 재선언이 불가하다. const는 재선언과 업데이트 모두 다 불가하다.
  3. 세 변수 모두 최상단으로 호이스팅이 되지만, var 변수만 undefined로 초기화되어지고, let과 const 변수는 초기화 되지 않는다.
  4. var과 let은 초기화하지 않은 상태로 선언할 수 있지만 (값을 지정해주지 않으면 undefined), const는 선언 중에 초기화를 해야한다.

ES2015(ES6) 등장 전에는 문제점들이 있음에도 불구하고, `var` 로 변수를 선언하는 것이 지배적이었다.

따라서 새로운 변수 선언 방식이 등장할 수 밖에 없었고, 우선 문제점에 대해 논의하기 전에 var 자체에 대해 더 이해를 해보자.

Var 

`var` 선언은 전역 범위 혹은 함수 범위로 지정이 된다. `var` 변수가 함수 외부에서 선언될 때의 범위는 전역이며, 즉 함수 블록 외부에서 사용을 하게 되면 모든 변수를 전체 윈도우 상에서 사용을 할 수 있다는 것이다.

 

`var`는 재선언되고, 업데이트 될 수 있다. 이때 `재선언`과 `업데이트` 라는 특징으로 인해 문제점을 가지게 된다.

    var greeter = "hey hi";
    var times = 4;

    if (times > 3) {
        var greeter = "say Hello instead"; 
    }
    
    console.log(greeter) // "say Hello instead"

times > 3true를 반환하기 때문에 greeter는 `say hello instead`로 재정의가 된다.

이를 의도적으로 재정의한 것이라면 괜찮겠지만, 변수 greeter은 이미 정의가 되어있다는 사실을 인식하지 못하는 경우에는 문제가 된다.

코드가 길어지고, 코드의 다른 부분에서 greeter 변수를 사용한 적이 있다면 뜻밖의 출력 결과에 놀랄 수 있다. 그리고 이는 많은 버그를 야기시킬 수 있다. 그래서 등장한 것이 `let`과 `const`이다. 

 

let

var는 전체 전역 범위, 함수 범위만 지원을 했지만 let은 전역범위, 함수범위, 블록범위까지 지원을 한다.

let test = false;


if (!test) {
    let init = "test";
}

console.log(init)

/* 
    console.log(init)
            ^

    ReferenceError: init is not defined
        at Object.<anonymous> (/Users/designer/fxxkalgo/hyeonwoo/자바스크립트 테스트 폴더/test.js:8:13)
        at Module._compile (node:internal/modules/cjs/loader:1101:14)
        at Object.Module._extensions..js (node:internal/modules/cjs/loader:1153:10)
        at Module.load (node:internal/modules/cjs/loader:981:32)
        at Function.Module._load (node:internal/modules/cjs/loader:822:12)
        at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:81:12)
        at node:internal/main/run_main_module:17:47
*/

let의 경우는 {} 블록 스코프에서만 사용이 가능한 특징을 가지고 있지만, 반면 var을 똑같은 위치로 코드를 작성하게 된다면,

let test = false;


if (!test) {
    var init = "test";
}

console.log(init)

// test

블록 스코프는 무시한 채, 전역 변수로써 init의 변수를 비정상적으로 출력이 되어진다.

let의 입장에서는 비정상적이지만, 그 전에 var을 절대적으로 사용했을 때는 비정상적인 출력이 아닐 수 있다

 

var과 마찬가지로 let은 해당 범위 내에서 업데이트가 가능하다. 하지만, var과 달리 let 변수는 범위 내에서 다시 재선언이 불가하다.

let greeting = "say Hi";
    greeting = "say Hello instead";
    
let greeting = "say Hi";
    let greeting = "say Hello instead"; // error: Identifier 'greeting' has already been declared

하지만, 동일한 변수가 다른 범위 내에서 정의된다면, 에러는 발생하지 않는다.

(아래 예제는 블록 스코프에서의 다른 범위 내, 동일 변수에 대한 내용이다)

    let greeting = "say Hi";
    if (true) {
        let greeting = "say Hello instead";
        console.log(greeting); // "say Hello instead"
    }
    console.log(greeting); // "say Hi"

Const

const로 선언된 변수는 일정한 상수 값을 유지한다. const 선언은 let 선언과 몇가지 유사한 점을 공유한다.

let 변수와 같이 const 변수도 선언된 블록 범위 내에서만 접근이 가능하며, const는 업데이트와 재선언이 불가능하다.

마치 벽돌과 같은 느낌이다.

const greeting = "say Hi";
    greeting = "say Hello instead";// error: Assignment to constant variable. 
    
const greeting = "say Hi";
const greeting = "say Hello instead";// error: Identifier 'greeting' has already been declared

따라 모든 const 선언은 선언하는 당시에 초기화가 되어야하며, Object의 경우는 다소 다른점이 존재한다.

const 개체는 업데이트를 할 수 없지만, Object의 '속성'은 업데이트가 가능하다.

const greeting = {
    message: "say Hi",
    times: 4
}

greeting = {
    words: "Hello",
    number: "five"
} // error:  Assignment to constant variable.
  // key를 추가하거나 새롭게 정의를 하지는 못한다.
    

// 이미 있는 key값의 속성에 대한 값을 바꾸는 것은 가능하다.
greeting.message = "say Hello instead";

변수에 따른 호이스팅

세 변수 모두 최상위로 호이스팅이 된다. 하지만 var 변수만 undefined로 초기화되고, let과 const 변수는 초기화되지 않는다.

 

댓글