Frontend/javaScript

[JavaScript] 호이스팅(Hoisting)

dddzr 2024. 7. 5. 17:22

호이스팅(hoisting) 이란?

  • 자바스크립트에서 변수와 함수의 선언이 해당 스코프의 최상단으로 끌어올려지는 것처럼 동작하는 특성입니다.
  • 선언은 스코프의 최상단으로 옮기지만, 초기화(할당)는 그 위치에서 그대로 이루어집니다.
  • 호이스팅은 함수와 변수를 다르게 처리합니다.

 

호이스팅(hoisting) 원인

  • 실행 컨텍스트의 생성 단계에서 변수와 함수의 선언이 미리 처리되기 때문에 발생합니다.
  • 실행 컨텍스트는 자바스크립트 코드가 실행되는 환경을 정의하며, 함수 호출 또는 전역 코드가 실행될 때마다 생성됩니다.
  • 실행 컨텍스트는 생성 단계와 실행 단계로 나뉩니다.
    • 생성 단계 (Creation Phase)
      • 변수와 함수 선언 처리: 실행 컨텍스트가 생성될 때, 자바스크립트 엔진은 먼저 현재 스코프 내의 변수와 함수 선언을 찾아서 메모리에 등록합니다. 이때 변수는 undefined로 초기화되고, 함수 선언은 실제 함수 객체로 초기화됩니다.
      • Lexical Environment 구성: 선언된 변수와 함수는 Lexical Environment에 등록됩니다. 이 환경은 스코프 내의 식별자와 그 바인딩을 저장합니다.
    • 실행 단계 (Execution Phase)
      • 코드 실행: 생성 단계가 완료된 후, 자바스크립트 엔진은 코드의 나머지를 순차적으로 실행합니다. 이때 변수 할당과 함수 호출이 이루어집니다.

 

변수 호이스팅 (Variable Hoisting)

자바스크립트에서 변수 선언은 `var`, `let`, `const` 키워드를 사용하여 이루어집니다. `var`로 선언된 변수는 호이스팅의 영향을 받지만, `let`과 `const`로 선언된 변수는 호이스팅의 영향을 받지 않습니다.

- var

  console.log(a); // undefined
  var a = 5;
  console.log(a); // 5

  위 코드에서 `var a` 선언이 최상단으로 호이스팅되어 실제로는 다음과 같이 동작합니다:

  var a;
  console.log(a); // undefined
  a = 5;
  console.log(a); // 5


  선언은 호이스팅되지만, 초기화는 그 위치에서 이루어집니다.

- let, const

  console.log(b); // ReferenceError: Cannot access 'b' before initialization
  let b = 10;
  console.log(b); // 10


  `let`과 `const`로 선언된 변수는 호이스팅되지만, 초기화 전에 접근하려고 하면 `ReferenceError`가 발생합니다. 이는 "일시적 사각지대(TDZ, Temporal Dead Zone)"에 의해 발생하는 것입니다.

 

함수 호이스팅 (Function Hoisting)

함수 호이스팅은 함수 선언 방식에 따라 다르게 동작합니다.

자바스크립트에서는 함수 선언과 함수 표현식의 두 가지 주요 방식이 있습니다.

- 함수 선언문 (Function Declaration)

  console.log(myFunc()); // "Hello, world!"
  function myFunc() {
    return "Hello, world!";
  }


  함수 선언은 완전히 호이스팅됩니다. 따라서 함수 선언 이전에 함수를 호출할 수 있습니다.

- 함수 표현식 (Function Expression)
 함수 표현식은 변수 호이스팅처럼 동작합니다. 즉, 함수 표현식이 할당되기 전에는 변수만 호이스팅되고 초기화되지 않습니다.

console.log(myFunc()); // TypeError: myFunc is not a function
var myFunc = function() {
  return "Hello, world!";
}

이처럼 자바스크립트의 호이스팅은 함수와 변수 선언에 다른 방식으로 적용됩니다. 이를 이해하면 코드를 작성할 때 예기치 않은 동작을 방지할 수 있습니다.

 

*함수 표현식에서 let 또는 const를 사용할 경우

변수의 경우와 같게 `ReferenceError`가 발생합니다.

console.log(myFunc); // ReferenceError: Cannot access 'myFunc' before initialization
let myFunc = function() {
  return "Hello, world!";
};
console.log(myFunc()); // "Hello, world!"