Posts [Javascript] 호이스팅
Post
Cancel

[Javascript] 호이스팅

호이스팅이란?

모든 변수 선언은 호이스트된다. 호이스트 란 변수의 정의가 그 범위에 따라 선언(declaration)/초기화(initialization)/할당 분리되는 것을 의미한다. 쉽게 말하면 변수가 함수내에서 정의되었을 경우 선언이 함수의 최상위로, 함수 바깥에서 정의되었을 경우는 전역 컨텍스트의 최상위로 변경됩니다.

1
2
3
4
5
6
7
8
9
10
const hoisting = () => {
  console.log("First-Name:", name);
  var name = "Marcus";
  console.log("Last-Name:", name);
}

hoisting();
// First Name : undefined
// Last Name : Marcus
// First Name이 undefined인 이유는 지역변수 name이 호이스트 되었기 때문이다.

위 hoisting 이라는 함수는 자바스크립트로 이해하면 다음과 같이 표현할 수 있다.

1
2
3
4
5
6
const hoisting = () => {
     var name; // name 변수는 호이스트 되었습니다. 할당은 이후에 발생하기 때문에, 이 시점에 name의 값은 undefined 입니다.
     console.log("First name : " + name); // First Name : undefined
     name = "Marcus"; // name에 값이 할당 되었습니다.
     console.log("Last Name : " + name); // Last Name : Marcus
}

그럼 여기서 궁금한점이 생길 수 있다. let 과 const에서는 호이스팅이 될까? 먼저 위에서 var로 작성한 hoisting이라는 함수를 let과 const로 바꿔보자.

1
2
3
4
5
6
7
const hoisting = () => {
  console.log("Name:", name);
  let name = "Marcus";
}

hoisting();
// ReferenceError: name is not defined

먼저 let으로 했을 경우 name is not defined라는 에러가 발생한다. 왜일까? 앞서 설명했을땐 변수가 함수내에서 정의되었을 경우 선언이 함수의 최상위로, 함수 바깥에서 정의되었을 경우는 전역 컨텍스트의 최상위로 변경된다 라고 설명했다. 이 이유를 설명하려면 우리는 Temporal Dead Zone(TDZ)라는 개념을 알아야한다.

자바스크립트에서는 총 3단계에 걸쳐서 변수를 생성한다.

  • 선언(Declaration): 스코프와 변수 객체가 생성되고, 스코프가 변수 객체를 참조한다.
  • 초기화(Initialization): 변수 객체 값을 위한 공간을 메모리에 할당한다. 이 때 할당되는 값은 undefined다.
  • 할당(Assignment): 변수 객체에 값을 할당한다.

var는 선언과 동시에 초기화가 이루어진다. 즉, 선언과 동시에 undefined가 할당된다.

그러나 let과 const는 다르다. 선언만 될뿐, 초기화가 이루어지지 않는다. 바로 이단계에서 TDZ에 들어가게 되는 것이다. 즉, TDZ란 변수가 선언은 되어있지만, 초기화가 되지 않아 이를 위한 자리가 메모리에 준비되어 있지 않은 상태라는 것이다.

다음 코드를 한 번 보자.

1
2
3
4
5
// const TDZ를 실행하기 전에 TDZ에 접근하면, TDZ에 의해 ReferenceError가발생하게 된다.
// console.log(TDZ); // output: ReferenceError: tdz is not defined

const TDZ = 'Temporal Dead Zone' // 위 코드 실행 이후에는 TDZ에 접근할 수 있다.
console.log(TDZ); // output: Temporal Dead Zone

변수 TDZ를 선언전, 실행 컨텍스트 변수 객체에 등록이 되어 호이스팅이 되지만, 이 TDZ 구간에 의해 메모리가 할당이 되질 않아 참조 에러(ReferenceError) 발생하는 것이다.

TDZ에 대해 더 자세한 내용을 알고 싶다면 여기를 참고하자.

정리

let/const선언 변수는 호이스팅되지 않는 것이 아니다. 스코프에 진입할 때 변수가 만들어지고 TDZ(Temporal Dead Zone)가 생성되지만, 코드 실행이 변수가 실제 있는 위치에 도달할 때까지 액세스할 수 없는 것이다. let/const변수가 선언된 시점에서 제어흐름은 TDZ를 떠난 상태가 되며, 변수를 사용할 수 있게 된다.

출처

This post is licensed under CC BY 4.0 by the author.

[Spring] P6Spy

[1장. 리액트 입문] 01. 리액트는 어쩌다 만들어졌을까?