치춘짱베리굿나이스
호이스팅 본문
Hoisting
console.log(a); // 1 ?!
var a = 1;
자바스크립트 단골 질문인 호이스팅이다
호이스팅 자체는 어떻게든 이해가 가더라도, 그 원리까지 공부하자니 온갖 선행 개념들이 많아 이 김에 정리해볼까 한다
왜 발생하고 어떻게 발생하는지 알아보도록 하자
설명
Hoist라는 영단어는 무언가를 끌어 올린다는 뜻을 가지고 있다
뜻을 풀었으니 한줄요약하자면 호이스팅은 변수나 함수의 선언을 맨 위로 끌어올린 것처럼 동작하는 현상이다
실제로 변수나 함수 선언이 최상단으로 끌어올려진 것은 아니고, 자바스크립트 엔진의 특성상 끌어올려진 것 처럼 동작하는 것 뿐이라고 한다
발생 이유
https://chichoon.tistory.com/921
실행 컨텍스트에 대해 필독하고 오자 (호이스팅은 실행 컨텍스트로 설명되기 때문)
사실 이 문서와 실행 컨텍스트 문서를 같이 작성하려다가 저 쪽이 너무 길어져서 분리했다
세줄요약 하자면
- 함수가 실행될 때 실행 컨텍스트가 생성되고, 그 후 실행된다
- 실행 컨텍스트가 생성되고 실행되기 전에 모든 변수나 함수의 선언부가 메모리에 등록된다
- 따라서 실행 컨텍스트가 실행되었을 때는 이미 변수와 함수의 선언이 등록된 이후이므로 변수와 함수 선언부가 코드 최상단으로 끌어올려진 것처럼 동작하게 된다
호이스팅이 발생하는 부분
var
console.log(a); // undefined
var a = 1;
var
은 호이스팅이 발생하는 대표적인 예시이다
위의 예시를 보면 선언 전에 값에 접근했음에도 오류가 나지 않고 실행되는 것을 볼 수 있다
선언만 끌어올려졌을 뿐 할당은 아직 일어나지 않았으므로, a
는 undefined
로 초기화되어 저장된다
따라서 undefined
가 출력되는 것
let, const와 TDZ
console.log(a); // a is not defined
let a = 1;
let
과 const
는 선언 전에 값을 사용하면 ReferenceError
오류가 발생하므로 호이스팅이 발생하지 않는 것처럼 보인다
하지만 let
과 const
도 (실행 컨텍스트 생성 시에 메모리에 적재되는 것은 똑같으므로) 호이스팅이 발생하고, 마치 호이스팅이 발생하지 않는 것처럼 보이는 것 뿐…
왜 let
과 const
는 호이스팅이 일어나지 않는 것처럼 보이는지 알고 싶다면 TDZ (Temporal Dead Zone) 을 알아야 한다
TDZ는 일시적 사각지대… 이라는 이름에서 알 수 있듯, 변수나 클래스 등이 일시적으로 접근 불가 상태에 빠지는 것을 말한다
let
과const
는 선언 시점에서 실행 컨텍스트에 등록된다- 하지만
undefined
로 임시 초기화되던var
와 달리,let
과const
는 초기화가 되지 않는다 (정확히 말하자면,uninitialized
상태로 초기화된다) let
,const
는 처음 값을 할당받는 (초기화되는) 코드를 마주할 때까지 TDZ에 빠지고, 이 상태에서let
과const
에 접근하면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");
}
};
함수 표현식과 클래스 표현식은 변수 안에 함수를 넣고 이를 호출하는 방식인데, 호이스팅 개념을 생각해 보면 처음 변수 foo
와 TestClass
는 실행 컨텍스트 적재 시점에 undefined
로 초기화되므로 함수를 호출하거나 생성자를 호출할 수 없다
console.log(foo);
var foo = function () {
console.log("hihi");
};
실제로 foo
에 함수를 할당하기 전 출력해 보면 undefined
가 찍히는 것을 볼 수 있다
참고 자료
https://tecoble.techcourse.co.kr/post/2021-04-25-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 |