[JS] var / let / const 비교

ziwon.k·2021년 9월 13일
0

[JS] 자바스크립트

목록 보기
1/9
post-thumbnail

변수 선언문 전에 변수에 접근할 수 있다고?😱
자바스크립트를 처음 배우면서 가장 헷갈렸던 부분에 대해서 정리해보았다.

0. var, let, const?

var let const 는 자바스크립트에서 변수를 선언할 때 사용하는 키워드.
변수를 사용하려면 반드시 선언이 필요하다!

1. 변수 생성(선언) 과정 비교

각 키워드 별로 변수 선언 시 어떤 차이점이 있는지 알아보자.

1.1 var 키워드를 통한 변수 선언

var 키워드로 선언된 변수는 다음과 같은 생명주기를 갖는다.
크게 코드가 한 줄 씩 실행되는 런타임 전런타임 후로 나눌 수있다.

런타임 전
1. 선언 단계 : 변수 이름을 실행 컨텍스트에 등록해서 자바스크립트 엔진에게 변수의 존재를 알린다.
2. 초기화 단계 : 값을 저장하기 위한 메모리 공간을 확보하고 암묵적으로 undefined를 할당해 초기화한다.
자바스크립트 엔진에 의해 항상 undefined로 초기화 되기 때문에 사실상 개발자가 따로 초기화를 해주지 않아도 쓰레기 값을 만나게 될 일은 없다.

런타임 후
개발자가 할당한 임의의 값으로 실질적 초기화(재할당)된다.
정확히 말하면 런타임 전에 자바스크립트 엔진에의해 암묵적으로 undefined로 초기화 된 후, 개발자가 할당한 임의의 값이 재할당 되는 것이므로 실질적 초기화라는 표현을 사용하였다.

console.log(sum);   //undefined
var sum = 0;        //변수 선언문

위에서 말했든var 키워드로 선언한 변수는 코드 실행 전 이미 변수가 선언되기 때문에 위와 같이 변수 선언문 전에 변수를 참조할 수 있는 변수 호이스팅 현상이 발생하는 것이다.


1.2 let 키워드를 통한 변수 선언

let 키워드로 선언된 변수는 다음과 같은 생명주기를 갖는다.
var 키워드와 비교해서 특이한 점은 선언 이후 undefined로 초기화 되기 전까지 변수에 접근할 수 없는 일시적 사각 지대 가 있다는 것이다.

var와 마찬가지로 let을 통해 선언한 변수도 런타임 전에 변수 선언이 이루어 진다.
하지만 바로 undefined가 할당되지 않고, 런타임 과정에서 변수 선언문에 도달하게 되면 undefined가 할당된다.
이때 변수 선언문에 도달하기 전까지 변수에 접근할 수 없는 구간을 일시적 사각 지대 라고 한다.
일시적 사각 지대일 때 변수에 접근할 경우 ReferenceError 가 발생한다.
변수 선언문에 도달한 후, 개발자가 임의의 값을 할당했을 경우에는 다시 해당 값이 재할당된다.


🧩 여기서 중요한 것은 let 키워드로 선언한 변수는 변수 호이스팅이 일어나지 않는 것 처럼 보인다는 것이다.
하지만 사실은 그렇지 않다.

let sum = 0;   //전역 변수
{ 
  console.log(sum);  //ReferenceError
  let sum = 10;   //지역 변수
}

만약 정말 let으로 선언한 변수가 호이스팅이 발생하지 않는다면, 위 예제에서 전역 변수 값인 0을 출력해야한다.
하지만 let 으로 선언한 변수도 호이스팅이 발생하기 때문에 ReferenceError 가 발생하는 것이다.
정리하자면 자바스크립트는 ES6에서 도입된 let, const를 포함한 모든 선언(var, function 등)을 호이스팅 한다.
단지 let, const의 경우 호이스팅이 발생하지 않는 것 처럼 동작하는 것 뿐이다!


1.3 const 키워드를 통한 변수 선언

위에서 말했듯이 const 를 사용한 변수 선언도 자바스크립트의 선언문에 포함되기 때문에 호이스팅이 발생한다.
하지만 let과 마찬가지로 일시적 사각 지대를 갖기 때문에 호이스팅이 발생하지 않는 것 처럼 동작한다.

{
  console.log(sum); //ReferenceError
  consot sum = 1;
  console.log(sum);
}

2. 스코프(유효 범위) 비교

2.1 var 의 스코프

var 키워드로 선언한 변수는 오로지 함수의 코드 블록만을 지역 스코프로 인정하는 함수 레벨 스코프를 따른다.
때문에 아래처럼 함수 블록이 아닌 코드 블록에서 변수 선언 시 모두 전역 변수가 된다.

var sum = 0;

if(true){
  var sum = 10;   //sum은 전역 변수, 이미 선언된 sum이 있지만, 중복 선언 되었다.
}
console.log(sum);   //10

2.1 let/const 의 스코프

let const 키워드로 선언한 변수는 모든 코드 블록(함수, if문, for문 등)을 지역 스코프로 인정하는 블록 레벨 스코프를 따른다.

const sum = 0;

{ 
  const sum = 10;
  const max_sum = 100 ;
}

console.log(sum);
console.log(max_sum)


3. 중복 선언 가능 여부 비교

3.1 var - 변수 중복 선언 허용

var 키워드로 선언한 변수는 다음과 같이 같은 스코프 내에서 중복 선언이 가능하다.

하지만 변수 중복 선언시 초기화문 유무에 따라서 약간의 차이가 있다.
1. 초기화 문이 있는 변수 (중복) 선언 : 자바스크립트 엔진에 의해 var 키워드가 없는 것 처럼 동작한다.
2. 초기화 문이 없는 변수 (중복) 선언 : 자바스크립트 엔진에 의해 무시된다 : undefined로 초기화 되지 않고, 에러도 발생하지 않는다.

때문에 변수가 이미 선언되어 있는 것을 모르고 중복 선언한 뒤 값을 할당했다면, 의도치 않은 변수 값 변경이라는 부작용이 발생할 수 있어 위험하다.

3.2 let, const - 변수 중복 선언 불가

반면 let const 로 선언한 변수의 경우 같은 스코프 내에서 중복 선언 할 경우 SyntaxError가 발생한다.


4. 재할당 가능 여부 비교

4.1 var, let - 재할당 가능

var let 키워드로 선언한 변수는 얼마든지 값을 재할당 할 수 있다.

4.2 const - 재할당 불가

const 키워드로 선언한 변수의 경우 재할당이 금지된다.
따라서 재할당 할 경우 다음과 같은 에러가 발생한다.

🧩 이때 주의할 점은, const 키워드는 재할당을 금지하는 것이지, 불변을 의미하는 것이 아니다.
새로운 값을 재할당 하는 것은 불가능 하지만, 배열의 원소를 추가, 삭제 하는 것과 같이 객체를 변경하는 것은 가능하다.
(객체가 변경되더라도 변수에 할당된 참조값(주소값)은 변경되지 않기 때문!)


5. 그렇다면, 어떤 키워드를 써야할까?

const 키워드를 사용해 변수를 선언하면 의도치 않은 재할당이 방지되기 때문에 조금 더 안전하다.
따라서, 변수 선언 시 기본적으로 const 를 사용하고 변수 값이 변경되거나 재할당이 필요한 경우에 한정해 let 키워드를 사용하는 것을 추천한다.


참고
모던 자바스크립트 Deep Dive

공부한 내용을 직접 정리한 글이라 잘못된 부분이 있을 수 있습니다. 혹시 잘못된 내용이 있다면 언제든지 알려주세요.🙂

profile
Frontend-Devloper

0개의 댓글