가치투자자

[JS/기술면접] 호이스팅(hoisting)이란? 본문

Programming/JavaScript

[JS/기술면접] 호이스팅(hoisting)이란?

미주민 2023. 3. 31. 23:07
728x90
반응형

 호이스팅 (Hoisting) 

공식문서를 살펴보면, 호이스팅(hoisting)은 '인터프리터가 변수와 함수의 메모리 공간을 선언 전에 미리 할당하는 것'을 의미한다고 나와있다.

역시 공식 문서의 용어들은 초보자가 공부하기에 쉽지 않다.

좀 더 쉬운 말로 호이스팅에 대해 설명해보고자 한다.

 

* 기술면접 질문은 맨 아래에 적혀 있습니다

 

728x90

1. 호이스팅이란?

호이스팅은 변수가 선언된 시점보다 먼저 실행되는 현상이다.

 

좀더 쉽게 설명해보자면, 변수가 어디에 적혀있든지(선언된 시점) 상관없이 맨 위로 끌어와 먼저 실행하는 것을 말한다.

여기서 var, let, const, function, function*, class 키워드를 사용해 선언된 모든 식별자(변수, 함수, 클래스 등)는 호이스팅된다.

아래의 예제를 통해 좀 더 쉽게 이해를 해보자.

 

* 모든 선언문은 런타임 이전 단계에서 먼저 실행되기 때문에, 위 키워드를 사용해 선언된 모든 식별자는 호이스팅된다

* 런타임(runtime) : 코드가 한 줄씩 실행되는 시점

 


2. 예제

1) 변수 호이스팅

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

console.log(a);  // 1

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

 

위 코드를 살펴보면, a가 console.log 앞에 선언되어 있지 않지만, 밑에 있는 변수 a를 맨 위로 끌어올려와  undefined라는 값을 불러올 수 있다.

 

let 역시 호이스팅되지만, 콘솔창에는 b를 찾을 수 없다는 참조에러(ReferenceError)가 뜬다.

let이 호이스팅 안 되어서 에러가 뜨는 것으로 생각할 수도 있지만, 에러 메시지를 자세히 보면 초기화(initialization) 전에 접근(access)할 수 없다고 나온다.

즉, 변수는 호이스팅으로 인해 선언되어 있지만, TDZ(일시적 사각지대)로 인해 아직 초기화가 되지 않아 접근이 안 되는 것이다.

 

 

참조에러가 뜨는 이유는 TDZ 게시글에서 좀 더 깊게 다루겠지만, 간단하게 이야기하자면 다음과 같다.

 

변수는 3단계에 걸쳐서 생성된다.

 

  1. 선언 단계 (declaration phase)
    : 변수를 (실행 컨텍스트의) 변수 객체에 등록한다. 즉, 변수가 등록(선언)된 것이다

  2. 초기화 단계 (initialization phase)
    : 변수에 값을 넣기 위한 공간을 메모리에 확보한다. 이 단계에서 변수는 undefined로 초기화된다.

  3. 할당 단계 (assignment phase)
    : undefined로 초기화된 변수에 실제 값을 넣어준다.

 

var 변수는 선언과 초기화가 한 번에 이루어진다.

그렇기에 변수 a의 값을 불러오기 위해 접근했을 때, 아직 실제 값이 "할당"되지는 않았지만, undefined라는 값을 불러올 수 있는 것이다.

 

 

 

 

반면, let과 const는 선언과 초기화 단계 사이에 TDZ(일시적 사각지대)라는 것이 존재한다.

아직 선언도 안 되어 있는데 접근한다면 심각한 에러가 발생할 수 있기에 이를 막기 위해 TDZ라는 것을 만들어 두었다.

 

 

 


2-1) 함수 호이스팅

// 함수 참조
console.log(sum);  // f sum(x, y)

// 함수 호출
console.log(sum(6, 8));  // 14

// 함수 선언문
function sum(x, y) {
  return x + y;
};

 

위 코드를 살펴보면, 함수 sum 역시 맨 위에 선언이 되어있지 않지만, 함수를 참고하고 호출할 수 있다.

이는 런타임 이전에 함수 이름과 동일한 이름의 식별자를 생성해 함수 객체에 할당해두기 때문에 가능하다.

 

2-2) 함수 표현식

// 함수 참조
console.log(sum);  // undefined

// 함수 호출
console.log(sum(6, 8));  // TypeError: sum is not a function

// 함수 표현식
var sum = function (x, y) {
  return x + yield;
};

함수 표현식으로 함수를 호출했을 경우엔 타입에러(TypeError)가 뜬다.

 

 

함수 표현식에 대해선 함수 게시글에서 다루겠지만, 간단하게 말해 함수의 타입은 객체이며, 이러한 객체 값(함수)을 변수에 할당해주는 방식이 함수 표현식이다.

함수 표현식은 함수 선언문과 달리 타입에러가 뜬다. 그 이유를 위에서부터 차근차근 살펴보자.

 

먼저, sum을 참조하면 undefined가 나온다.

즉, var 변수에 접근했기에 undefined를 출력해주는 것이다. 하지만 앞서 살펴봤듯이 아직 실제 값이 할당되지 않았기 때문에 undefined를 출력해준다. 그리고 함수 표현식에서 실제 값은 "함수"이다.

실제 함수 값을 console.log 이전에 할당해주지 않았기 때문에 undefined라는 값을 출력하고, sum의 타입은 undefined이기에 sum의 타입이 함수가 아니라는 에러 메시지가 뜨는 것이다.

 

 


3. 변수 호이스팅과 함수 호이스팅 공통점/차이점

그렇지만 함수 호이스팅과 변수 호이스팅은 미묘하게 다르다.

 

  • 공통점
    : 변수 호이스팅과 함수 호이스팅은 런타임 이전에 실행되어 식별자를 생성한다는 점에서 동일하다

  • 차이점
    : var 변수는 undefined로 초기화되고, 함수 식별자는 함수 객체로 초기화된다.
    : 따라서 var 변수를 참조하면 undefined로 평가되지만, 함수 선언문 이전에 함수를 호출할 수 있다.

 

반응형

 


🌟 자바스크립트 기술면접 질문

1. 호이스팅이란 무엇인가? 🔥🔥

 

  • 변수가 선언된 시점보다 먼저 실행되는 현상을 말하며, 변수, 함수, 클래스 등의 식별자들이 호이스팅된다.

 

2. 변수 호이스팅과 함수 호이스팅의 공통점과 차이점은 무엇인가?

 

  • 둘다 런타임 이전에 실행되어 식별자를 생성한다는 점에서 공통점이 있다.
  • 그러나 var 변수 선언문을 선언 이전에 참조하면 undefined가 출력되는 반면, 함수 선언문 이전에 함수를 호출하면 함수를 호출할 수 있다.

 


</> 끊임없이 성장하기 위해 공부한 내용을 글로 작성하고 있습니다. 틀린 부분이나 추가해야 할 부분이 있다면 언제든 댓글로 남겨주세요❗️

 


References

 

728x90
반응형