호이스팅이란?

💡 호이스팅이란 코드드가 실행하기 전 변수선언/함수선언
이 해당 스코프의 최상단으로 끌어 올려진 것 같은 현상을 말한다.
함수 호이스팅
함수 선언의 종류
함수 선언문
function add(x, y) {
return x + y;
}
- 변수에 할당할 수 없다.
- 함수 이름을 생략할 수 없다.
- 런타임 이전에 자바스크립트 엔진에 의해 함수 객체가 먼저 생성됨
- 런타임에서 함수 선언문이 실행되기 이전에 함수를 참조할 수 있으며 호출할 수도 있다.
console.log(add(2, 5));
function add(x, y) {
return x + y;
}
함수 표현식
var sub = function(x, y){
return x - y;
}
- 변수에 할당할 수 있다.
- 함수 이름을 생략할 수 있다.(익명함수)
- 함수 표현식은 변수에 할당되는 값이 함수 리터럴인 문이다.
- 함수 호이스팅이 발생하는 것이 아니라 변수 호이스팅이 발생.
- 함수 표현식으로 정의한 함수는 반드시 함수 표현식 이후에 참조, 호출해야 한다.
console.log(sub(2, 5));
var sub = function(x, y){
return x - y;
}
함수 호이스팅이란?
💡 함수 선언문이 코드의 선두로 끌어올려진것 처럼 동작하는 **자바스크립트 고유의 특징**
- 함수를 호출하기 전에 반드시 함수를 선언해야한다는 당연한 규칙을 무시
파이썬에서는 호이스팅이 일어나지 않는다.

c에서도 호이스팅이 일어나지 않아 앞에 선언을 다시 적어줘야 정상적으로 작동한다.
💡 JSON 창안한 더글라스 크락포트 왈
함수 선언문 대신 함수 표현식을 사용할 것을 권장
Javascript 의 변수 생성 단계

1. 선언 단계 (Declaration phase)
- 변수를 실행 컨텍스트의 변수 객체에 등록하는 단계
- 모든 선언문은 런타임 이전에 먼저 실행된다.
- 자바스크립트 엔진은 코드를 실행하기 전 실행 컨텍스트를 위한 과정에서 모든 선언(var, let, const, function, class)을 스코프에 등록한다.
2. 초기화 단계 (Initialization phase)
let foo;
- 실행 컨텍스트에 등록한 변수를 위한 메모리를 만드는 단계
- 메모리가 만들어지면 처음에는
undefined
가 할당
3. 할당 단계 (Assignment phase)
foo = 123;
- 사용자가 undefined 로 할당된 변수에 다른 값을 할당하는 단계
키워드 별 함수/변수 생성 단계
function (함수 선언문)

- 선언, 초기화, 할당 단계가 동시에 이루어집니다.
- 런타임 이전에 자바스크립트 엔진에 의해 함수 객체가 먼저 생성
function add(x, y) {
return x + y;
}
console.log(add(2, 5));
var

- 선언과 초기화 단계가 동시에 진행
- 런타임 이전에 선언 단계와 초기화 단계가 실행
- 할당 단계는 할당문에서 실행
- 변수 선언문 이전에 변수를 참조할 수 있다.
console.log(foo_var);
var foo_var = 123;
let, const (+ class)

- 선언, 초기화, 할당 단계가 각각 따로 이루어집니다.
- 런타임 이전에는 선언 단계만 실행
- 초기화 단계는 변수 선언문에 도달했을 때 실행
- 초기화 단계가 실행되기 이전(일시적 사각지대에서)에 변수에 접근하려고 하면 참조 에러가 발생
const
키워드로 선언한 경우, 선언과 초기화(초기화단계와 할당 단계)가 동시에 이루어져야 하지만 런타임 이전에는 실행될 수 없다.
- let 예시
console.log(foo_let);
let foo_let = 123;
- const 예시
console.log(foo_const);
const foo_const = 123;
- 클래스(Class)도 동일하다.
console.log(Tester);
**class** Tester{
constructor(){
this.name = "test";
}
}
💡 런타임 이전에 호출했을 때 어떤 결과가 나오는지를 생각하면 된다.
모든 식별자는 호이스팅된다. 모든 선언문은 런타임 이전에 먼저 실행되기 때문이다.
일시적 사각지대 (TDZ)

- TDZ(Temporal Dead Zone)
- 임시 접근 불가구역이라고도 함
- 스코프의 시작점부터 초기화 단계(변수 선언문)전까지
- 이 구간에 있는 변수를 참조하게 되면 에러가 발생한다.
그러면 let, const, class 는 호이스팅되지 않는가?
❌ 모든 식별자는 호이스팅된다.
let, const, class도 호이스팅되지만, 호이스팅이 발생하지 않는 것처럼 동작할 뿐이다.
❓ let, const
let foo = 1;
{
console.log(foo);
let foo = 2;
}
Uncaught ReferenceError: Cannot access 'foo' before initialization
- let 키워드로 선언한 변수의 경우 호이스팅이 발생하지 않는다면 위 예제는 전역변수 foo의 값을 출력해야 한다. 하지만 let 키워드로 선언한 변수도 여전히 호이스팅이 발생하기 때문에 참조 에러가 발생한다.
- 변수 선언문 이전에 일시적 사각지대에 빠진다.
❓ class는?
const Person = ''
{
console.log(Person);
class Person {}
}
Uncaught ReferenceError: Cannot access ‘Person’ before initialization.
- 클래스 선언문으로 정의한 클래스는 함수 선언문과 같이 소스코드 평가 과정, 즉 런타임 이전에 먼저 평가되어 함수 객체를 생성한다. 이때 클래스가 평가되어 생성된 함수 객체는 생성자 함수로서 호출할 수 있는 함수, 즉 constructor이다. 생성자 함수로서 호출될 수 있는 함수는 함수 정의가 평가되어 함수 객체를 생성하는 시점에 프로토타입도 더불어 생성된다. 프로토타입과 생성자 함수는 단독으로 존재할 수 없고 언제나 쌍으로 존재하기 때문이다.
- 클래스 선언문 이전에 일시적 사각지대에 빠지기 때문에 호이스팅이 발생하지 않는 것처럼 동작한다.