JS - 자바스크립트 호이스팅과 변수의 생성과정에 대해

들어가며 

  ES6의 대표적인 Keyword를 뽑으라고 한다면 아마 자바스크립트에서 변수를 선언할 때 사용하는

3가지 Keyword인 var, let, const를 생각해볼 수 있다.

 

이번 포스팅에서는 이러한 var, let, const에 차이에 대해서 자세하게 정리하고자한다.

 

 

 

let과 var의 차이점

  var와 let은 크게 다르지 않기에 대부분의 경우에는 둘을 바꿔서 사용해도 문제가 생기지 않는다.

그렇다면 다른점은 무엇일까?

 

1. var는 한번 선언된 변수를 다시 선언할 수 있다.

var name = 'Mike';
console.log(name);

var name = 'Jane';
console.log(name);

혼돈의 var

하지만 let은 한번 선언된 변수를 다시 선언할 수 없다.

 

let name = 'Mina';
console.log(name);

let name = 'Minsu';
console.log(name);

정상적으로 느껴지는 error 메시지의 let

 

왜 그럴까?

 

호이스팅

 var로 선언한 모든 변수는 최상위로 끌어올려진 것처럼 동작한다. 이것을 호이스팅이라하는데

이때 선언은 호이스팅되지만 할당은 호이스팅되지 않기 때문에 에러를 뱉어내지는 않지만 출력하고자하면 undefined

라고 찍어준다.

 

같은 상황에서 let은 에러를 내뱉는데 let은 호이스팅되지 않기 때문일까?

이에 대한 대답은 No, let도 호이스팅은 된다. 

 

호이스팅이란 '우선적으로 변수의 선언 단계가 메모리에 저장되었다'라는 것을 의미한다.

즉, 선언이 끌어올려진다 라는 의미이기 때문에 자바스크립트의 모든 선언에는 호이스팅이 일어난다.

 

다만 let, const, class를 이용한 선언문들은 호이스팅이 발생하지 않은 것처럼 동작한다.

왜 그럴까?

 

바로 일시적 사각지대(Temporal Dead Zone : TDZ)에 영향을 받기 때문이다.

바로 이 TDZ 영역에 있는 변수들은 사용할 수 없다. let과 const는 바로 TDZ에 영향을 받는 것이다.

여기서 TDZ란 스코프의 시작 지점부터 초기화 시작 지점까지의 구간을 말한다.

 

 

그렇다면 아래 코드의 TDZ는 어디서부터 어디일까?

let age = 30;
function showAge() {
  console.log(age);
  let age = 20;
}

showAge();

 

정답은 아래와 같다.

showAge() 스코프가 2번째라인부터 시작되고 있으며  초기화 시작이 4번째라인(let age= 20)에서

진행되고 있기 때문이다.

 

따라서 만약 let이 호이스팅되지 않는다면 최상단에 선언된 let age =30에 의해서 console.log()에서는 30이 찍혀야한다.

하지만 let도 호이스팅이 되기에 showAge() 스코프안에 선언된 let age= 20; 에 의해서 이미 선언된 변수라고 에러를 뱉는 것이다.

 

 아니 그러면 var 도 let도 둘다 호이스팅이 되는데 왜 let은 호이스팅이 되지 않는 것처럼 동작하는가??

그것은 바로 let으로 선언하는 변수의 생성과정이 var 로 선언된 변수와는 다르기 때문이다.

 

우선 let 변수들은 3단계를 거쳐서 변수가 생성이 되는 반면 var 변수들은  2단계를 거쳐 생성된다

 

변수의 생성과정

위와 같이 var변수와 let 변수 둘다 호이스팅이  일어남에도 서로 다르게 동작하는 것을 이해하는데 있어서

필요한 개념이 변수의 생성과정이다.

 

변수의 생성과정은 아래와 같이 3단계로 구분지어볼 수 있다.

 

1. 선언 단계

2. 초기화 단계

3. 할당 단계

 

- var 변수의 생성과정은 2단계로 이루어진다.

 1. 선언 및 초기화 단계가 한꺼번에 이루어짐

 2. 할당 단계

이와 같이 var 변수는 선언과 동시에 초기화 단계가 이루어지기 때문에 선언전에 호출하더라도 에러가 안나고 undefined가 초기화되어 들어간다.

 

- let 변수의 생성과정은 3단계로 이루어진다.

1. 선언단계

2. 초기화 단계

3. 할당 단계

 

이것이 바로 let 변수가 TDZ의 영향을 받는 이유이다.

 

 var 변수와 다르게 const와 let변수는 선언단계와 초기화 단계가 분리되어서 진행된다.

let으로 선언한 변수도 var 변수와 마찬가지로 선언단계 부분은 호이스팅되어 이루어지는 것은 동일하지만

초기화 단계는 호이스팅되지 않고 실제 코드에 도달했을 때 이루어지기 때문에 에러를 내뱉는 것이다.

 

결론

  결국 왜 var 로 변수를 선언하는 것을 지양해야 하는가? 이에 대한 대답은
 let과 const는 var와는 달리 블록 단위 범위(block-scoped)를 가지며, 변수의 스코프가 선언된 블록 내부로 제한된다.
이로써 변수 충돌을 방지하고, 코드의 가독성과 유지보수성을 높일 수 있기 때문이다.

'JavaScript' 카테고리의 다른 글

JS - eval 함수 보안 취약점  (0) 2022.04.29
JS - 생성자 함수  (0) 2022.04.27
JS - toggle  (0) 2021.11.20
JS - Event listener  (0) 2021.11.16
JS - localStorage 다루기 와 preventDefault()  (0) 2021.04.04