## 호이스팅이란? 호이스트란 무언가를 끌어올리는 것을 의미한다. ![[91053946-845e-434e-86f9-1df64210cf3e.png]] 자바스크립트에서 호이스팅이란 **변수나 함수 선언이 해당 스코프의 최상단으로 끌어올려지는 것**이다. 실제로 코드가 물리적으로 이동하는 것은 아니고 자바스크립트 엔진이 실행 컨텍스트를 생성하는 과정에서 함수나 변수의 선언을 메모리에 등록하는 과정이다. 선언이 최상단으로 끌어올려졌기 때문에 변수 선언 이전에도 변수에 접근할 수 있다. ```javascript console.log(a); // undefined var a = 10; ``` ## 호이스팅 동작 차이 ### var 선언 var로 선언한 변수는 스코프 상단으로 끌어올려지면서 자동으로 undefined가 할당된다. ```javascript var name; console.log(name); // undefined console.log(typeof name); // "undefined" ``` ### let, const 선언 let과 const로 선언한 변수도 호이스팅된다. 하지만 자동으로 초기화되지 않기 때문에 선언 이전에 접근하는 경우 ReferenceError가 발생한다. ```javascript console.log(b); // ReferenceError let b = 2; ``` 이렇게 변수는 호이스팅되지만 초기화되기 전까지 접근이 불가능한 영역을 [[#TDZ 란?|TDZ]]라고 한다. ### 함수 선언 함수 선언의 경우 선언과 함께 구현부까지 모두 호이스팅된다. 따라서 함수를 선언하기 전에도 호출할 수 있다. ```javascript // 함수 선언 전에 호출 가능 console.log(sayHello()); // "Hello!" - 정상 실행 function sayHello() { return "Hello!"; } ``` **함수 표현식**의 경우에는 **변수 호이스팅 규칙**을 따른다. 변수는 호이스팅되지만 **함수 할당은 런타임에** 일어나기 때문이다. ```javascript console.log(sayHello); // undefined console.log(sayHello()); // TypeError: sayHello is not a function var sayHello = function () { return "Hello!"; } ``` 따라서 let과 const로 선언된 함수 표현식은 [[#TDZ 란?|TDZ]]의 영향을 받는다. ```javascript console.log(sayHello); // ReferenceError: sayHello is not defined const sayHello = () => { return "Hello!"; }; ``` ### 호이스팅 우선순위 함수 선언이 var 변수 선언보다 우선해서 호이스팅된다. ```javascript console.log(typeof test); // "function" - 변수가 아닌 함수로 인식 var test = "I am a variable"; function test() { return "I am a function"; } console.log(typeof test); // "string" - 런타임에서 변수 할당이 실행됨 ``` 따라서 **함수 선언문은 코드 상단**에, **함수 표현식은 사용하기 전에 선언**하는 것을 권장한다. <!--todo: 왜?--> ## TDZ 란? TDZ(Temperal Dead Zone)이란 let, const로 선언된 변수들이 선언되기 전까지 접근할 수 없는 공간이다. TDZ 안에서 변수에 접근하는 경우에는 ReferenceError가 발생한다. ```javascript console.log(x); // ReferenceError: x is not defined let x = 5; ``` **핵심 원리** 1. let/const로 선언된 변수는 스코프 생성 시점에 호이스팅되어 메모리에 등록된다. 2. 하지만 초기화는 선언 라인이 실행될 때 까지 지연 3. 해당 공간에는 (말 그대로) 아무 값이 없는 상태가 된다. (uninitialized) 4. 스코프의 시작부터 선언 라인 전까지 영역에서 접근하면 참조 에러가 발생하는 것 <!--todo:\ 블록 스코프에서... 1. 각 블록마다 독립적인 TDZ 2. 중첩된 스코프에서 외부와 내부 변수의 shadowing (같은 이름의 변수가 다른 스코프에서 선언될 때 발생하는 현상. 쉐도잉이 발생하면 내부 스코프의 변수가 외부 스코프의 변수를 가려서 내부 스코프 변수를 참조하게 됨) 3. 함수 내부 변수와 매개변수의 TDZ 상호작용 --> ## 관련 문서 - [[변수 선언 방식]]