Post

호이스팅

호이스팅(Scope)이란?

- MDN docs -
인터프리터가 변수와 함수의 메모리 공간을 선언 전에 미리 할당하는 것을 의미합니다.

다시 말해, 스코프 안에 있는 선언들을 모두 스코프의 최상위로 끌어올리는 것이다.

자바스크립트 엔진은 코드를 실행하기 전 컴파일 단계에서 함수와 변수 선언이 스캔된다. 스캔된 모든 함수, 변수 선언은 Lexical Environment라고 불리는 자바스크립트 데이터 구조 내 메모리에 추가된다.

자바스크립트 엔진은 우리가 정의한 함수나 변수를 마주치면, 해당 함수와 변수를 Lexical Environment를 살펴보고, 있을 경우 실행시킬 수 있게된다.


ex) 호이스팅 예시

1
2
3
4
5
helloWorld(); // Hello World!

function helloWorld() {
  console.log("Hello World!");
}

위의 예시에서 helloWorld를 선언하기 전에 호출하였지만 “Hello World”가 출력되는 것을 볼 수 있다.

이는 helloWorld함수가 호이스팅 되었기 때문에 즉, 최상단으로 끌어 올려져 문제 없이 출력되는 것이다.

호이스팅은 var, let, const 에서 그리고 함수 선언식, 표현식에서 다르게 동작된다.

먼저 var, let, const에서의 호이스팅을 알아보았다.




var, let, const의 호이스팅

let과 const는 변수 호이스팅(variable hoisting)이 발생하지만, 다른 변수 선언 방식인 var와는 동작이 다르다.

1. var

  • 선언과 동시에 undefined로 초기화 됨.
case 1. 호이스팅 전case 2. 호이스팅 후
console.log(myVar);
var myVar = 10;
var myVar; // undefined로 초기화
console.log(myVar);
myVar = 10;
undefined 출력undefined 출력

2. let, const

  • 선언만 될뿐, 초기화가 이루어지지 않음.

  • 호이스팅이 일어나지만 초기화가 되지 않아 let선언부 위는 TDZ이 됨.

  • const키워드는 선언과 동시에 초기화 되어야 하므로 const선언부 위는 TDZ이 됨.

case 1. 호이스팅 전case 2. 호이스팅 후
console.log(myVar);
let myVar = 10;
let myVar; // 초기화 되지 않음
console.log(myVar);
myVar = 10;
ReferenceError: myVar is not defined 에러 출력ReferenceError: myVar is not defined 에러 출력

* TDZ(Temporal Dead Zone)
let과 const로 선언한 변수는 호이스팅되면서 해당 변수가 할당되기 전까지 일시적 사각지대(TDZ)에 머물게 된다.
TDZ 내에서 변수에 접근하려고 하면 ReferenceError가 발생한다.


결론적으로, let과 const는 호이스팅되지만 TDZ와 블록 스코프의 특징으로 인해 변수가 선언되기 전에 접근하려는 에러를 미리 감지할 수 있어 코드의 안정성을 향상시킨다.




함수 선언식과 표현식에서의 호이스팅

1. 함수 선언식

  • function

  • 함수 전체 정의된 범위의 맨 위로 호이스팅되어 함수 선언 전에 함수를 사용할 수 있다.

case 1. 호이스팅 전

1
2
3
4
5
6
sum(50, 50); // 100

function sum(a, b) {
  // 함수 선언식
  return a + b;
}

case 2. 호이스팅 후

1
2
3
4
5
6
function sum(a, b) {
  // 함수 선언식 - 함수 전체 호이스팅
  return a + b;
}

sum(50, 50); // 100

2. 함수 표현식

  • arrow function, let minus = function ()

  • 함수를 별도의 변수에 할당하는 것을 함수 표현식이라 한다.

  • 변수는 선언부와 할당부를 나누어 호이스팅 하며 선언부만 호이스팅 한다.

case 1. 호이스팅 전

1
2
3
4
5
6
minus(100, 50); // Uncaught TypeError: minus is not a function

// 함수 표현식
var minus = function (a, b) {
  return a - b;
};

case 2. 호이스팅 후

1
2
3
4
5
6
7
var minus; // 함수표현식 - 선언부만 호이스팅

minus(100, 50) // Uncaught TypeError: minus is not a function

function (a,b) { // 함수 표현식 - 할당부는 그대로
return a - b;
}

함수 선언식으로 작성한 함수는 함수 전체가 호이스팅 되는데 이를 전역적으로 선언 혹은 중복적으로 동명의 함수를 쓰게 된다면 원치 않는 결과를 초래할 수 있다.

함수 표현식으로 작성하게되면 함수를 선언하기 전의 부분에서는 해당 함수를 사용할 수 없기 때문에 위의 같은 상황을 방지할 수 있다.




📑 참고 자료

[인간 JS 엔진 되기]-제로초

[javascript] 변수의 선언 할당 초기화 / var let const 완벽 비교 정리

호이스팅과 TDZ는 무엇이고 어떤 연관이 있을까요?

This post is licensed under CC BY 4.0 by the author.