본문으로 건너뛰기
홈
기술
기술 전체
프로그래밍68
컴퓨터 과학63
AI48
웹 개발36
인프라33
데이터31
소프트웨어 공학18
소개
← 목록으로프로그래밍 › JavaScript › 언어 기능

호이스팅(Hoisting)

목차

호이스팅 (Hoisting)

호이스팅은 선언을 소스 코드의 맨 위로 실제로 이동한다는 뜻이 아니라, 스코프가 시작될 때 선언이 먼저 등록되는 동작을 설명하는 비유다. 선언 종류에 따라 초기화 시점이 달라진다.

함수 선언과 함수 표현식

sayHello(); // Hello
function sayHello() {
  console.log('Hello');
}

console.log(typeof sayBye); // undefined
// sayBye(); // TypeError: sayBye is not a function
var sayBye = function () {
  console.log('Bye');
};
sayBye(); // Bye

함수 선언은 실행 전에 함수로 준비된다. var sayBye 선언도 등록되지만 처음 값은 undefined다. 함수 표현식이 대입되는 줄을 지나야 호출할 수 있다. 원래 메모의 travel 예제에서도 함수 선언이 있더라도 travel = 'No Plan'로 문자열을 대입한 뒤 travel()을 호출하면 TypeError가 난다.

let과 const의 초기화 전 접근

{
  // console.log(count); // ReferenceError
  let count = 1;
  console.log(count); // 1
}

let과 const도 블록의 스코프에 등록되지만 선언문에 도달하기 전에는 접근할 수 없다. 이 구간을 일시적 사각지대(TDZ)라고 부른다. var가 함수 스코프를 갖는 것과 달리 두 선언은 블록 스코프를 갖는다.

기존 예제에는 travel/traval, goToGym/goToGyn처럼 이름이 달라 실행 순서를 해석하기 어려운 부분이 있었다. 호이스팅을 확인할 때는 예제를 각각 따로 실행하고, 선언 등록과 값 대입을 구분해 살펴보면 된다.

같은 이름이 블록 안팎에 있을 때

let과 const의 TDZ는 같은 블록 안에서 바깥 변수보다 안쪽 선언이 우선하는 경우에도 나타난다.

const value = "바깥";
{
  // console.log(value); // ReferenceError: 아래 let 선언의 TDZ
  let value = "안쪽";
  console.log(value); // 안쪽
}
console.log(value); // 바깥

주석의 console.log는 바깥 value를 읽지 않는다. 블록 안의 let value 선언이 이미 같은 이름을 차지하지만 아직 초기화되지 않았기 때문이다. 이 현상은 파일 맨 위로 선언이 실제 이동했다는 설명보다 스코프 등록과 초기화 시점으로 이해해야 정확하다.

function example() {
  console.log(message); // undefined
  var message = "준비";
  console.log(message); // 준비
}
example();

함수 선언, var 변수, let·const 선언의 초기화 시점이 다르다. 특히 값이 undefined인지, 접근 자체가 ReferenceError인지 구분하면 버그의 위치를 찾기 쉽다. 선언보다 앞에서 이름을 사용해야 할 특별한 이유가 없다면 선언과 초기화를 사용 지점보다 먼저 두는 편이 명료하다.

참고: MDN Hoisting

같은 카테고리의 글