호이스팅이란?

일반명사) 끌어 올리기

고유명사) 선언한 위치와 상관없이 함수, 변수의 선언부를 인접한 스코프의 최상단으로 끌어올려 스코프 내 어디서든 해당 식별자를 관측할 수 있는 현상

호이스팅은 어떻게 발생하는가?

하지만 자바스크립트 엔진은 실제로 코드를 실행하는 시점에 함수, 변수의 선언부를 인접한 스코프의 최상단으로 끌어올릴 만한 능력이 없다. 단지 코드 실행 전에 어떤 과정을 거쳐서 변수, 함수에 대한 전체적인 정보를 미리 알고 있을 뿐이다.

여기서 말하는 어떤 과정이란

참고) 자바스크립트는 코드 실행 전 따로 컴파일 과정을 거친다.

컴파일 : 사람이 이해하는 언어로 이루어진 코드를 컴퓨터가 이해할 수 있도록 쪼개고, 체계적인 구조로 재가공하여 전체를 분석하는 일련의 과정

자바스크립트 엔진은 코드 실행 전 모든 스코프를 탐색하며 각 스코프의 변수 객체에 여러 식별자를 수집한다.

즉 코드 실행 시점으로 넘어가기 전에 선언된 식별자에 대한 정보를 이미 알고 있기 때문에 스코프의 어느 지점이든 관련된 함수/변수를 참조할 수 있는 것이다.

호이스팅 규칙

호이스팅은 크게 함수 호이스팅과 변수 호이스팅으로 나뉜다.

  • 선언된 함수는 스코프의 어느 지점이든 참조, 호출이 가능하다.
  • var 로 선언된 변수는 스코프의 어느 지점이든 참조, 할당이 가능하다.
  • let, const 로 선언된 변수는 스코프의 어느 지점이든 참조, 할당이 불가능하다.

1. 함수 호이스팅

함수의 선언문만 호이스팅이 일어난다.

함수의 선언문은 식별자가 인접한 스코프의 변수 객체에 수집될 때 부가적으로 해당 함수의 참조에 대한 초기화까지 자동으로 이루어진다.

이 덕분에 함수를 호출하는 코드를 함수 선언보다 앞서 배치할 수 있다.

 

예시) 함수 선언문 이후에 함수 호출 (일반적인 코드 작성 순서)

function dogName(name) {
    console.log("제 강아지의 이름은 " + name + "입니다.");
}

dogName("멍멍이");

/*
결과: "제 강아지의 이름은 멍멍이입니다."
*/

예시) 함수 선언문 이전에 함수 호출 (함수 호이스팅 발생)

dogName("멍멍이");

function dogName(name) {
    console.log("제 강아지의 이름은 " + name + "입니다.");
}

/*
결과: "제 강아지의 이름은 멍멍이입니다."
*/

 

함수 표현식은 호이스팅이 일어나지 않는다.

함수 표현식은 어떤 변수에 함수를 할당하는 것처럼 보여 변수 호이스팅의 사례로 보여질 수 있다.

예시)

var value = 'value';
var func = function () { }

 

2. 변수 호이스팅

변수는 어떻게 선언했는지에 따라 선언, 초기화 시점이 달라질 수 있다.

 

var 는 호이스팅이 발생하면 선언과 초기화가 거의 동시에 이루어진다. 실행 시점의 스코프 최상단에서 해당 변수에 대한 메모리가 살아 있기 때문에 선언부 위치에 상관없이 참조, 할당이 가능하다.

let, const 는 호이스팅이 발생하면 선언만 이루어지고 실행 시점에서 실질적인 선언부를 만날 때까지 초기화는 이루어지지 않는다.

이 간극만큼 해당 변수에 대한 메모리는 존재하지 않기 때문에 선언부 상단에서 참조, 할당이 불가능하다.

일시적 사각지대(TDZ(Temporal Dead Zone)) : let, const 가 동작하는 과정에서 스코프의 진입 지점과 해당 식별자의 실질적 선언부 사이, 여기서 식별자는 존재하지만 초기화되어 있지 않다.

변수 호이스팅 예시

예시) var 호이스팅

console.log(num); // 호이스팅한 var 선언으로 인해 undefined 출력
var num; // 선언
num = 6; // 초기화

예시) 선언 없이(호이스팅 X) 초기화만 존재

console.log(num); // ReferenceError: num is not defined
num = 6; // 초기화

예시) var 호이스팅

// 예제 1
// b 만 호이스팅 대상

a = 2; // a 초기화. a 를 선언하지 않은 경우 선언. 그러나 var 가 없으므로 호이스팅이 발생하지 않음.
console.log(a + " " + b); // '2 undefined'
// JavaScript 는 선언만 호이스팅하므로, 윗줄의 b 는 undefined
var b = 3; // b 를 선언하고 초기화

예시) let, const 호이스팅

{
    /*
     Temporal Dead Zone of a
     a 는 이 구간에서 참조할 수 없다.
     console.log(a); // Reference Error
    */
    let a;
}

예시) let, const 호이스팅

console.log(a); // ReferenceError: Cannot access 'a' before initialization
// let 호이스팅이 일어나 전역 스코프의 변수 객체에 식별자는 수집됐으나 초기화가 이루어지지 않음.
let a;

참조

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

https://developer.mozilla.org/ko/docs/Glossary/Hoisting

 

'프로그래밍 언어 > JavaScript' 카테고리의 다른 글

JavaScript 의 동작방식  (0) 2022.11.12
[JavaScript] 반복문  (0) 2022.11.05
[JavaScript] 실행 컨텍스트  (0) 2022.11.05
[JavaScript] 스코프(Scope)  (0) 2022.11.05
[JavaScript] 런타임 메모리 구조  (0) 2022.11.05
복사했습니다!