JavaScript

[JavaScript] var, let, const 비교 (+ 호이스팅 이해하기)

Chae-ri🍒 2024. 6. 28. 01:57

ES6에서 let, const가 도입되기 이전까지는 var 키워드를 통해 변수를 선언하였다.

하지만 var 키워드의 여러 문제점 때문에 이 문제점들을 보완하기 위해 let과 const가 등장한 것인데,

var의 문제점은 무엇이고 var, let, const 세 키워드의 차이점과 여기서 쓰이는 개념인 호이스팅에 대해 알아보자.

 

var 키워드 사용의 문제점

1. 중복 선언 가능

var a = 10;
var a = 30;
console.log(a); // 30

var는 중복으로 선언이 가능하다. 동일한 이름의 변수를 선언해도 에러가 발생하지 않기에 의도치 않은 문제가 발생할 수 있다.

2. 함수 레벨의 스코프

스코프란, 변수가 사용될 수 있는 영역이라고 보면 된다.

var 키워드로 선언한 변수는 함수의 코드 블록을 지역 스코프로 본다.

따라서, 함수 코드 블록 밖에서 선언된 변수는 전역 변수가 된다.

    var a = 1;
    if(a === 1){
      var b = 2;
    }

    function func(){
      var c = 3;
      return;
    }

    console.log(a); // 1
    console.log(b); // 2
    console.log(c); // undefined

 

3. 호이스팅 발생

호이스팅

먼저 호이스팅이란, 소스코드가 순차적으로 실행되는 런타임 이전 단계에서 변수 선언을 포함한 모든 선언문(변수 선언문, 함수 선언문 등)을 평가한다. 즉, 변수 선언문이 스코프의 최상단으로 끌어 올려진 것처럼 동작하는 현상을 말한다. 

변수 선언 뿐만 아니라 var, let, const, function, class 키워드를 사용해서 선언하는 모든 식별자는 호이스팅 된다.

    console.log(a); // undefined

    var a = 1;
    console.log(a); // 1

호이스팅에 의해 이미 a 변수가 먼저 선언이 된 상태이고 이 때 undefined로 초기화가 된다.

첫 번째 콘솔에는 undefined가 출력이 되고

 

var a = 1; 에서 1이 할당이 된다.

그래서 두 번째 콘솔에는 1이 출력이 되는 걸 볼 수 있다.

 

var 키워드는 런타임 이전에 암묵적으로 선언 단계와 초기화 단계가 한 번에 진행된다.

 


 

이런 var의 문제점을 보완하기 위해 나타난 let과 const에 대해 알아보자.

 

let

1. 중복 선언 불가능, 재할당 가능

중복 선언이 가능한 var과 달리, let은 중복 선언이 불가능하다.

var가 가지고 있던 중복 선언으로 인해 발생할 수 있는 의도치 않은 문제를 방지할 수 있다.

let a = 10;
let a = 20; // SyntaxError: Identifier 'a' has already been declared
a = 20;
console.log(a);

 

2. 블록 레벨 스코프

모든 코드 블록을 지역 스코프로 간주한다.

예) 함수, if, switch, 반복문, try catch 등

 

선언된 블록 밖에서 해당 변수를 참조한다면 ReferenceError가 발생한다.

let a = 1;
    if(a ===1){
      let b = 1;
      console.log(b); // 1
    }
console.log(b); // ReferenceError : b is not defined

3. 호이스팅이 발생하지 않는다. (정확히는 발생하지 않는 것처럼 동작한다!)

let은 var과 달리, 선언 단계와 초기화 단계가 분리되어 진행된다.

 

런타임 이전에 선언 단계가 먼저 실행되고 변수 선언문에 도달했을 때 초기화 단계가 실행된다.

console.log(a); // ReferenceError: a is not defined
let a = 20;
console.log(a); // 20

 

const

1. 중복 선언 불가능, 재할당 불가능(+ 선언과 초기화 동시에)

const는 중복 선언이 불가능하며, 재할당도 불가능하다.

추가적으로 const는 선언과 초기화를 동시에 문에 포함해야 한다.

const a; // SyntaxError: Missing initializer in const declaration
const b = 10;
b = 3; // TypeError : Assignment to constant variable
console.log(b); // 10

 

재할당이 불가능하다고 해서 const 변수가 아예 불변한다는 것은 아니다.

const person = {name : "Julia"};
console.log(person); // {name : "Julia"}
obj.age = 20;
console.log(person); // {name : "Julia", age : 20}

person = {name : "James"} // TypeError : Assignment to constant variable.

위 예시처럼 const 키워드로 선언된 객체는 객체 프로퍼티 변경이 가능하다.

새로운 객체를 재할당하는 것이 불가능!

2. 블록 레벨 스코프

let과 똑같이 const도 블록 레벨 스코프를 가진다.

function foo () {
    let a = 10;
    if (true) {
        let a = 20;
        console.log(a); // 20
    }
    console.log(a); // 10
}

foo();

3. 호이스팅이 발생하지 않는다. (정확히는 발생하지 않는 것처럼 동작한다!)

let과 똑같이 const도 호이스팅이 발생하지 않는 것처럼 동작한다.

    function foo(){
      console.log(a);
      const a = 1;
    }
    foo(); // ReferenceError : Cannot access 'a' before initialization

호이스팅이 먼저 일어나고 a에 대한 초기화가 일어나기 전에 a에 접근하기 때문에 ReferenceError가 뜨는 것을 볼 수 있다.

 

💡일시적 사각지대 - TDZ(Temporal Dead Zone)

let과 const로 선언한 변수는 스코프의 시작 지점부터 초기화가 되기 전까지 참조할 수 없는 구간을 일시적 사각지대 - TDZ(Temporal Dead Zone) 라고 한다. 

{
  console.log(a); // ReferenceError: a is not defined
  let a = 10;
  console.log(a); // 10
}

블록 안에 호이스팅이 발생하여 변수 선언이 먼저 일어나고, var과 다르게 초기화 단계가 변수 선언문에 도달할 때까지 지연되기 때문에 일시적 사각지대가 발생한다.

728x90