치춘짱베리굿나이스

호이스팅 본문

Javascript + Typescript/이론과 문법

호이스팅

치춘 2023. 8. 24. 16:12

Hoisting

console.log(a); // 1 ?!

var a = 1;

자바스크립트 단골 질문인 호이스팅이다

호이스팅 자체는 어떻게든 이해가 가더라도, 그 원리까지 공부하자니 온갖 선행 개념들이 많아 이 김에 정리해볼까 한다

왜 발생하고 어떻게 발생하는지 알아보도록 하자

설명

Hoist라는 영단어는 무언가를 끌어 올린다는 뜻을 가지고 있다

뜻을 풀었으니 한줄요약하자면 호이스팅은 변수나 함수의 선언을 맨 위로 끌어올린 것처럼 동작하는 현상이다

실제로 변수나 함수 선언이 최상단으로 끌어올려진 것은 아니고, 자바스크립트 엔진의 특성상 끌어올려진 것 처럼 동작하는 것 뿐이라고 한다

발생 이유

https://chichoon.tistory.com/921

실행 컨텍스트에 대해 필독하고 오자 (호이스팅은 실행 컨텍스트로 설명되기 때문)

사실 이 문서와 실행 컨텍스트 문서를 같이 작성하려다가 저 쪽이 너무 길어져서 분리했다

세줄요약 하자면

  • 함수가 실행될 때 실행 컨텍스트가 생성되고, 그 후 실행된다
  • 실행 컨텍스트가 생성되고 실행되기 전에 모든 변수나 함수의 선언부가 메모리에 등록된다
  • 따라서 실행 컨텍스트가 실행되었을 때는 이미 변수와 함수의 선언이 등록된 이후이므로 변수와 함수 선언부가 코드 최상단으로 끌어올려진 것처럼 동작하게 된다

호이스팅이 발생하는 부분

var

console.log(a); // undefined

var a = 1;

var은 호이스팅이 발생하는 대표적인 예시이다

위의 예시를 보면 선언 전에 값에 접근했음에도 오류가 나지 않고 실행되는 것을 볼 수 있다

선언만 끌어올려졌을 뿐 할당은 아직 일어나지 않았으므로, aundefined로 초기화되어 저장된다

따라서 undefined가 출력되는 것

let, const와 TDZ

console.log(a); // a is not defined

let a = 1;

letconst는 선언 전에 값을 사용하면 ReferenceError 오류가 발생하므로 호이스팅이 발생하지 않는 것처럼 보인다

하지만 letconst도 (실행 컨텍스트 생성 시에 메모리에 적재되는 것은 똑같으므로) 호이스팅이 발생하고, 마치 호이스팅이 발생하지 않는 것처럼 보이는 것 뿐…

letconst는 호이스팅이 일어나지 않는 것처럼 보이는지 알고 싶다면 TDZ (Temporal Dead Zone) 을 알아야 한다

TDZ는 일시적 사각지대… 이라는 이름에서 알 수 있듯, 변수나 클래스 등이 일시적으로 접근 불가 상태에 빠지는 것을 말한다

  1. letconst는 선언 시점에서 실행 컨텍스트에 등록된다
  2. 하지만 undefined로 임시 초기화되던 var와 달리, letconst는 초기화가 되지 않는다 (정확히 말하자면, uninitialized 상태로 초기화된다)
  3. let, const는 처음 값을 할당받는 (초기화되는) 코드를 마주할 때까지 TDZ에 빠지고, 이 상태에서 letconst에 접근하면 ReferenceError가 발생한다

클래스

const b = new TestClass();

class TestClass {}

클래스 또한 TDZ의 영향을 받으며, 메모리에 적재되는 건 같지만 uninitialized 상태로 초기화되어 실질적인 클래스 선언 전까지 사용이 불가능하다

함수 선언문

foo();

function foo() {
    console.log("hihi");
}

함수 선언문은 호이스팅이 일어나며, 변수 등등과 다르게 undefined로 초기화되지 않고 아예 실행 컨텍스트가 생성되는 방식이기 때문에 함수를 호출해도 정상적으로 동작한다

덕분에 함수 순서를 조금 더 유연하게 배치할 수 있게 되는 것

함수와 클래스 표현식

foo();

var foo = function () {
    console.log("hihi");
};

const b = new TestClass();

var TestClass = class {
    constructor() {
        console.log("hihi");
    }
};

함수 표현식과 클래스 표현식은 변수 안에 함수를 넣고 이를 호출하는 방식인데, 호이스팅 개념을 생각해 보면 처음 변수 fooTestClass 는 실행 컨텍스트 적재 시점에 undefined로 초기화되므로 함수를 호출하거나 생성자를 호출할 수 없다

 

console.log(foo);

var foo = function () {
    console.log("hihi");
};

실제로 foo 에 함수를 할당하기 전 출력해 보면 undefined가 찍히는 것을 볼 수 있다


참고 자료

https://tecoble.techcourse.co.kr/post/2021-04-25-hoisting/

https://blinders.tistory.com/90

https://velog.io/@cada/모던-자바스크립트에서의-호이스팅Hoisting

'Javascript + Typescript > 이론과 문법' 카테고리의 다른 글

비동기와 콜백 함수 ver. 2023  (0) 2023.09.19
실행 컨텍스트  (0) 2023.08.23
any, unknown, never  (0) 2023.08.21
var, let, const 차이점  (0) 2023.08.17
문자열의 특정 문자 변경하기  (0) 2023.08.08
Comments