var, let ,const 의 차이


:raising_hand: Javascript 관련 공부내용을 기록하는 포스트 입니다.


image

1. 개요


이번에는 Javascript 의 타입 var, let, const 에 대하여 포스팅을 진행한다.

중간중간 Scope에 대한 기술도 들어갈 예정이다.

2. 함수레벨 스코프와 블록레벨 스코프


스코프(Scope)는 식별자의 유효범위를 뜻하며, 선언된 위치에 따라 유효 범위가 달라진다.

전역변수는 어디에서든지 스코프 체이닝을 통해 참조가 가능하다.

위 내용은 실행컨텍스트 생성과정에서 자세히 확인할 수 있다.

Javscript에서 if, for, while ,try/catch등이 지역 스코프를 만들며, 이러한 특성을 블록 레벨 스코프라 한다.

하지만, var로 선언된 변수의 경우 오직 함수의 코드블록 만을 지역 스코프로 인정한다.

이를 함수 레벨 스코프라 한다.

3. var, let, const 의 차이점


이제는 var, let, constScope의 차이에 대해서 확인해보자.

3-1. var

위 설명에서 이미 var의 경우 함수레벨 스코프를 가지기 떄문에 함수Block만을 지역 스코프로 인정한다고 했다.

따라서, var로 선언된 변수가 블록 스코프 안에 있다면 지역변수가 아닌 전역변수와 같은 스코프를 가진다.

아래의 예를 한번보자.

const array = [];

for (var i = 0; i < 10; i++) {
  array.push(function () {
    console.log(i);
  });
}

array[0](); // 10
array[1](); // 10
array[2](); // 10
array[3](); // 10
array[4](); // 10

console.log("i : ", i); // i :  10

function test() {
  var a = 1;
}

console.log("a : ", a); // Uncaught ReferenceError: a is not defined

Javascript 에서 var함수 스코프에서만 지역변수를 가진다고 하였다.

위 소스에서 보면 i 값은 var로 선언되었고, for 반복문에서는 var는 전역변수와 같은 스코프를 가진다.

따라서, for문이 다돌고 호출하게되면 i 를 호출 할 수 있고 결과는 10이 나오게 된다.

반면, test함수의 내부 변수인 a의 경우 함수 스코프에서는 지역 스코프를 가지기 떄문에 함수 밖에서는 사용할 수 없는것을 확인할 수 있다.

3-2. let,const

반면 let,const블록 레벨 스코프를 가지기 때문에 블록 내에서는 지역 스코프를 가진다.

const array = [];

for (let i = 0; i < 10; i++) {
  array.push(function () {
    console.log(i);
  });
}

array[0](); // 1
array[1](); // 2
array[2](); // 3
array[3](); // 4
array[4](); // 5

//console.log("i : " ,i) // Uncaught ReferenceError: i is not defined

function test() {
  let a = 1;
}

console.log("a : ", a); // Uncaught ReferenceError: a is not defined

위 코드를 보면 var와는 사뭇 다른 결과값이 나온다.

우선 for문이 돌면서 생성된 렉시컬 환경의 변수인 i값을 for문이 끝나고도 array에 담긴 function상위 스코프의 변수 i를 참조할 수 있다.

따라서 이는 정상적으로 값이 노출될 수 있는 것이다.

3-3. 선언 및 초기화의 차이

Javscript 는 코드를 실행할때 실행 컨텍스트라는 환경정보를 구성하며 실행된다.

자세한 정보는 실행 컨텍스트 포스팅을 참조하면 된다.

이러한 과정에서 var, let ,const 간의 차이가 발생하게 된다.

첫번째로, var의 경우에는 Creation Phase에서 선언될 떄 Environment Record선언과 동시에 undefined로 값을 초기화 한다.

이는 우리가 알고있는 호이스팅 이 일어나는 원인이 된다.

반면, let의 경우 렉시컬 환경을 구성할 때 Creation Phase에서는 선언만 진행하고 실제 Execution Phase에서 값을 할당하게 된다.

이때문에 var, let, const 모두 호이스팅이라는 상황은 동일하게 발생하지만 선언이전에 값을 호출하면 let의 경우 레퍼런스 오류가 발생하게 되는 것이다.

const선언, 초기화, 할당을 모두 동시에 진행하게 된다.

따라서, let 과 동일하게 동작한다.

위와 같은 이유로 var의 경우 재선언, 재할당이 가능하고, let재할당만 가능하며, const모두 불가 하다.

4. 결과 정리


var함수 스코프를 가지며 let, const블록 스코프를 갖습니다.

따라서, var 로 선언된 변수는 함수 스코프외의 스코프에서는 전역 변수로 설정된다. 반면, let, const 의 경우 블록 스코프를 갖기 때문에 블록 내부에서만 사용가능하며 외부에서 사용이 불가능하다.

var 의 경우 렉시컬 환경이 구성될때 선언과 초기화가 동시에 이루어지기때문에 호이스팅이 발생하고 TDZ 에 영향을 받지 않습니다.

반면, let선언초기화분리되어 호이스팅이 발생은 하지만, TDZ 의 영향을 받아 레퍼런스 에러가 발생합니다. const선언, 초기화, 할당동시에 이루어지므로 재할당불가능합니다.

참조 사이트