본문 바로가기

JavaScript

Hoisting & Temporal Dead zone (TDZ)

Hoisting

  • 사전적의미: 끌어올리다, 들어올리다
  • javascript에서 변수가 선언되기 전에 사용 될 수 있다는 것을 의미합니다.

함수 안에 있는 선언들을 모두 끌어올려서 해당 함수 유효 범위의 최상단에 선언.

    여기서 유효 범위는 함수 블록 {} 안을 말합니다.

호이스팅의 대상

자바스크립트에서는 ES6에서 도입된 let, const를 포함한 모든 선언을 호이스팅합니다.

변수는 3가지 단계를 거쳐 생성 됩니다.

  • 선언 단계 (Declaration Phase): 변수를 변수 객체 (Variable Object)에 등록합니다. 이 변수 객체는 스코프가 참조하는 대상이 됩니다.
  • 초기화 단계 (Initialization Phase): 변수 객체 (Variable Object)에 등록된 변수를 위한 공간을 메모리에 확보합니다. 이 단계에서 변수는 undefined로 초기화됩니다.
  • 할당 단계 (Assignment Phase): undefined로 초기화된 변수에 실제 값을 할당합니다.

 

💡 var 키워드로 선언된 변수는 선언 단계와 초기화 단계가 한번에 이루어집니다.
→ 초기화 단계에서 undefined로 초기화되기 때문에 변수 선언문 이전에 변수에 접근해도 에러가 발생하지 않고 undefined를 반환하는 것입니다.

 

var hoisting Example

<!-- 예제1 -->

callByName(name) // 'My name is '
console.log(name) // undefined

function callByName(name) {
	console.log(`My name is ${name}`);
}

var name = 'jay'

/* 아래와 같이 작동 */
var name;
function callByName(name) {
	console.log(`My name is ${name}`)
}
callByName(name); // 'My name is '
console.log(name); // undefined
name = 'jay';

<!-- 예제2 -->

CallByName("jay");   // 함수 선언 전에 함수를 호출 -> hoisting 이 되어 잘 작동한다. 

function CallByName(name){  // 함수 선언. 
    console.log(name);
}

//PhoneNumber(123);   // 작동하지 않는다

var PhoneNumber = function(number) {  // 함수의 선언 방식이 아니기 때문에 hoisting 되지 않는다. (only work on function declaration)
    console.log(number);
}

//variables (변수)

console.log(age); // 작동은 되지만 undefined로 뜬다. (hoisting) -> js 가 변수가 선언되었는지는 알고 있는 것이다. 

// 변수의 선언만 호이스팅.

var age = 20;  //global 

console.log(age);

function foo(){
    var age = 65; //local
    console.log(age);   //local print
}

foo();  
console.log(age);  // global print

 

💡 반면 let, const 키워드로 선언된 변수는 선언 단계와 초기화 단계가 분리되어 이루어집니다.
따라서, 스코프에 변수를 등록(선언단계)하지만 초기화 단계는 변수 선언문에 도달했을 때 이루어지므로 초기화 이전에 변수에 접근하면 참조 에러(ReferenceError)가 발생하는 것입니다.

 

let hoisting Example

console.log(name) // ReferenceError
let name = 'jay'

Temporal Dead Zone (TDZ)

  • 초기화되지 않은 변수가 있는 곳을 Temporal Dead Zone이라고 합니다.
  • let, const 는 초기화 되기 전까지 TDZ에서 대기하게 되고,
  • 변수가 초기화되는 순간 TDZ에서 나오게 되며 사용할 수 있게 되는 것입니다.
let value = "out Scope";

function hoisted() {
  // value가 TDZ에 영향을 받는 순간
  console.log("value", value); // value ReferenceError
  let value = "inner scope"; // value가 초기화 됨으로써, TDZ가 끝나게 됩니다.
};

hoisted();
여기서 let 변수가 hoisting 되지 않았다면, ReferenceError가 아닌 outScope가 찍혔을 겁니다.
TDZ는 초기화가 되지 않은 바인딩에 접근할 때, 미리 초기화하라고 에러를 알려주는 역할을 합니다.

 

 

 

참고

https://velog.io/@holim0/Front-End-%EB%A9%B4%EC%A0%91-%EC%A7%88%EB%AC%B8-%EB%8C%80%EB%B9%84-Part1-hoisting-closure-this

https://velog.io/@wrfg12/ES6-Hoisting-Temporal-Dead-ZoneTDZ