JavaScript의 Hoisting

코드 실행 전 실행 컨텍스트를 생성하는 과정에서 변수, 함수, 클래스의 선언 정보를 수집합니다.

#JavaScript

자바스크립트 인터프리터는 전역공간, eval() 함수, 함수 등을 실행하기 전 실행할 코드에 관한 환경 정보를 모은 객체를 생성합니다. 이 객체를 실행 컨텍스트라고 부르는데, 실행 컨텍스트를 생성하는 과정에서 변수, 함수, 클래스의 선언 정보를 수집합니다(단, 값 할당 정보는 수집하지 않습니다). 실행 컨텍스트는 실제 코드가 실행되기 전에 생성되므로 자바스크립트 인터프리터는 코드를 실행할 때 이미 해당 스코프의 모든 변수, 함수, 클래스의 선언 정보를 가지고 있는 상태가 됩니다. 이로 따라 아래와 같은 현상이 발생하게 되며 이러한 현상을 ‘Hoisting(호이스팅)’이라고 부릅니다.

  • 변수 선언 코드보다 앞선 코드에서 해당 변수의 값을 사용할 수 있습니다.
  • 변수 선언 코드보다 앞선 코드에서 해당 변수를 ReferenceError 없이 참조할 수 있습니다. 이때 undefined 값을 반환합니다. (단, const, let을 이용한 선언일 경우 ReferenceError가 발생합니다)
  • 변수 선언 코드가 자신보다 앞선 코드에 영향을 줄 수 있습니다.

변수 선언 코드보다 앞서 변수값 사용

a();
function a() {}; // -> (1)
  • 함수 선언이 있으므로 코드 실행에 앞서 수집합니다. 단, 함수는 선언과 함께 함수 내용이 함께 수집됩니다. 전역공간 실행 컨텍스트에 함수 a가 추가되었습니다.
  • 코드 실행 - 실행 컨텍스트에 존재하는 함수 a를 정상적으로 호출합니다.
function a() {
    console.log(b); // ƒ b() {}
    var b = 1; // -> (1)
    console.log(b); // 1
    function b() {}; // -> (2)
    console.log(b); // 1
}
a();
  • (1) - 변수 선언이 있으므로 코드 실행에 앞서 수집합니다. 함수 a 실행 컨텍스트에 변수 b가 추가되었습니다.
  • (2) - 함수 선언이 있으므로 코드 실행에 앞서 수집합니다. 함수 a 실행 컨텍스트에 이미 변수 b가 있으므로 이를 덮어씁니다. 이제 변수 b의 값은 함수 b 입니다.
  • 코드 실행 - 첫 번째 console.log(b) 실행 시 실행 컨텍스트에 변수 b가 존재하므로 그 값인 function b() {}가 출력됩니다. 이후 값 1 할당 코드가 실행된 이후부터는 1이 출력됩니다.

변수 선언 코드보다 앞서 변수 참조

console.log(a); // Uncaught ReferenceError: a is not defined

console.log(b); // undefined
var b = 1; // (1)
  • (1) - 변수 선언이 있으므로 코드 실행에 앞서 수집합니다. 전역공간 실행 컨텍스트에 변수 b가 추가되었습니다.
  • 코드 실행 - 변수 a는 존재하지 않으므로 ReferenceError가 발생하지만 변수 b는 비록 값은 할당되지 않았지만 수집된 선언 정보가 있으므로 이를 참조하여 undefined를 반환합니다.

변수 선언 코드보다 앞선 코드에 영향

const x = 1; // -> (1)
{
  console.log(x); // ReferenceError
  const x = 2; // -> (2)
}
  • (1) - 상수 선언이 있으므로 코드 실행에 앞서 수집합니다. 전역공간 실행 컨텍스트에 상수 x가 추가되었습니다.
  • (2) - 상수 선언이 있으므로 코드 실행에 앞서 수집합니다. 블럭 실행 컨텍스트에 상수 x가 추가되었습니다.
  • 코드 실행 - 전역공간에 상수 x가 존재하지만 자신의 스코프인 블럭 실행 컨텍스트에 상수 x가 있으므로 이를 우선 참조합니다. 아직 선언된 값이 없고, const로 선언되었으므로 ReferenceError가 발생합니다. 만약 (2) 코드가 없었다면 전역공간에 선언된 상수 x 값을 참조하였을 것입니다. 코드 (2)는 자신보다 앞선 코드인 console.log(x) 실행에 영향을 주었습니다.

참고


Profile picture

Jinsol Kim

Developer. Busan, South Korea.

#React #ReactNative #NextJS #iOS #Swift