[JS] var, let, const 비교

hyeondoonge·2022년 11월 8일
1

var, let, const이 3가지 키워드는 자바스크립트에서 변수를 선언할 때 사용할 수 있다.
let, const는 es6부터 추가된 문법이며 var 이후에 등장했다.
이 글은 각 키워드를 재선언과 재할당, 유효범위 그리고 호이스팅 관점에서 비교하고있다. 이를 통해 let과 const의 등장을 이해해보자.

1. 재선언과 재할당

var

재선언, 재할당 모두 가능하다.

function greeting() {
  var greeting = 'hello';
  var greeting = 'bye';

  console.log(greeting); // bye
}

greeting(); 
function greeting() {
  var greeting = 'hello';
  greeting = 'bye';

  console.log(greeting); // bye
}

greeting(); 

let

var과 달리 재선언은 불가능하다. 하지만 var과 동일하게 재할당은 가능하다.
흔히 사용하는 변수라고 생각하면 된다.

function greeting() {
  let greeting = 'hello';
  let greeting = 'bye';

  console.log(greeting); // Identifier 'greeting' has already been declared
}

greeting(); 
function greeting() {
  let greeting = 'hello';
  greeting = 'bye';

  console.log(greeting); // 'bye';
}

greeting(); 

const

재선언과 재할당 모두 불가능하다.

function greeting() {
  const greeting = 'hello';
  greeting = 'bye';

  console.log(greeting); // Assignment to constant variable.
}

greeting(); 

2. 유효 범위

값의 유효범위는 해당 값에 접근할 수 있는 스코프(범위)를 얘기한다.
따라서 정해진 스코프 내에서 어디서든 접근가능하고 외부에서는 접근하지 못함을 의미한다.

var

function scope를 따른다.
function scope는 값의 유효범위가 함수 스코프임을 뜻한다. 아래와 같이 동일한 함수안에 있다면 특정한 값을 사용할 수 있다.
선언된 함수를 기준으로 모든 하위 함수는 이 스코프에 속한다.

function greeting() {
  while (1) {
    var greet = 'hello';
    break;
  }
  console.log(greet); // hello
}

greeting();

let, const

block scope를 따른다.
block scope는 값의 유효범위가 블록 스코프임을 뜻한다. 동일한 블록({ })안에 있다면 특정한 값을 사용할 수 있다.
아래와 같이 var키워드를 사용할 땐 잘 동작하던 코드가, let을 사용했을 때는 에러가 발생하는 걸 볼 수 있다.
값이 선언된 블록을 기준으로, 모든 하위 블록도 스코프에 속하며 하위블록에서도 접근가능하다. (앞서 설명한 function scope와 동일)

function greeting() {
  while (1) {
    let greet = 'hello';
    break;
  }
  console.log(greet); // greet is not defined
}

greeting();

3. 호이스팅

값의 선언부할당부가 분리되어, 값의 선언부가 코드 내 최상단으로 끌어올려지는 것을 말한다. (이런 특징 때문에 코드 상에서 값이 정의되기 전에 참조할 수 있다)
실제로 동작방식은 인터프리터가 코드를 실행하기 전에, 선언에 대한 메모리 공간을 미리 할당해준다.
중요한 것은 var인 값은 undefined값으로 초기화되며, let과 const인 값들은 메모리 공간만 할당될 뿐 값이 초기화되지 않는다.
무슨 말인지 아래 코드를 보면서 더 이해해보자.

var

인터프리터가 미리 greet에 대한 메모리 공간을 할당하고, undefined로 값을 초기화했다.
아래 코드처럼 greet 출력 시, 호이스팅 때문에 undefined가 출력된다.

function greeting() {
  console.log(greet);

  var greet = 'hello';
}

greeting(); // undefined

let, const

var과 달리 메모리 할당과 동시에 값이 초기화되지 않는다.
아래 코드처럼 greet를 출력하는 시점에는 변수가 초기화되지 않는 상태이다. 때문에 초기화되지 않는 값에 접근하려는 시도를 했기때문에 에러가 발생하게 된다.

function greeting() {
  console.log(greet);

  let greet = 'hello';
}

greeting(); // ReferenceError: Cannot access 'greet' before initialization

값을 선언할 때 사용하는 키워드 (var, let, const)들은 설명한 것과 같이
크게 재선언 및 재할당, 스코프(유효범위), 호이스팅 관점에서 비교했다.
글을 작성하면서 var은 모든 관점에서 좀 더 자유로운 키워드인 것 같다고 생각했다. 그래서 개발자마다 var을 사용하는 방식이 다양할 것 같다.
이런 부분이 var로 작성된 코드를 이해하기 어렵게 만드는 것이 아닐까...
또, C++이나 Java와 같은 언어에서의 변수 선언 방식과 다른부분 때문에 그렇게 생각할 수도 있을 것 같다.

참고

let
호이스팅

0개의 댓글