[JS] 호이스팅이란?

jiny·2025년 1월 16일

기술 면접

목록 보기
24/78

🗣️ 자바스크립트의 호이스팅에 대해 설명해주세요.

  • 의도: 호이스팅에 대해 이해하고 있고, 어떤 오류가 호이스팅 때문인가 구분할 수 있는지 확인하는 질문

  • 나의 답안

    호이스팅스코프 내에서 변수 선언 및 함수 선언코드의 실행 단계 전스코프의 최상단으로 끌어올려지는 동작을 의미합니다.
    이는 자바스크립트의 컴파일링 과정에서 발생하며, 변수와 함수의 선언부만 끌어올려지고, 초기화나 할당은 끌어올려지지 않는다는 특징이 있습니다.

    호이스팅이 발생하는 이유는 자바스크립트의 실행 과정과 연관이 있습니다.
    자바스크립트는 실행 전에 코드를 두 단계로 처리합니다.
    처음은 컴파일 단계로, 변수를 선언하고, 함수 선언을 스코프의 최상단으로 이동시킵니다.
    그 다음은 실행 단계로, 코드를 위에서 아래로 읽으며 실행합니다.
    호이스팅은 컴파일 단계에서 발생하므로, 실행 전에 선언이 스코프의 맨 위로 이동된 것처럼 보이게 됩니다.

    호이스팅 동작 방식은 크게 변수 선언, 함수 선언, 클래스 선언마다 조금씩 다릅니다.
    우선, var로 선언된 변수는 선언이 호이스팅되지만, 초기화는 호이스팅되지 않습니다.
    따라서 선언 전에 접근하면 undefined를 반환합니다.
    letconst선언은 호이스팅되지만, 일시적 사각지대(TDZ: Temporal Dead Zone)에 의해 초기화 전에 접근할 수 없습니다.

    함수 선언은 변수와 달리, 전체 함수 정의가 호이스팅됩니다.
    따라서 함수 선언 전에 호출할 수 있습니다.
    그러나 함수 표현식은 호이스팅되지 않으며, 변수 호이스팅 규칙을 따릅니다.

    클래스 선언호이스팅되지만, 초기화 전에 접근하면 ReferenceError가 발생합니다.

    호이스팅은 코드의 동작을 예상하기 어렵게 만들 수 있습니다.
    따라서 var보다는 letconst를 사용하는 것이 좋고, 되도록이면 변수 선언은 코드의 최상단에서 수행하는 것이 좋습니다.
    그리고 함수 선언문과 함수 표현식을 명확히 구분하여 사용하는 것이 좋습니다.

  • 주어진 답안 (모범 답안)

    호이스팅의 영어 뜻은 "끌어올리다"입니다.
    그렇기에 자바스크립트의 호이스팅도 끌어올린다는 의미인데요.
    바로 코드 실행 전에 변수 선언과 함수 선언을 스코프의 최상단으로 끌어올리는 것을 뜻합니다.

    원래 C언어 같은 프로그래밍 언어를 사용했을 때는 변수나 함수가 무조건 상단에 선언이 되어 있어야 했습니다.
    그래야 아래 줄에서 참조가 가능하기 때문입니다.
    하지만 자바스크립트는 실제로 선언된 위치와 상관없이 최상단으로 선언부가 끌어올려지기에 선언 위치 앞에서도 호출이 가능해집니다.
    다만 이게 함수, var, let/const의 경우에 따라 달라집니다.

    함수의 경우에는 어디서든 호출이 가능하고 제대로 작동합니다.
    하지만 var의 경우에는 선언 전에 호출한다면 undefined를 반환하게 됩니다.
    그러나 이게 오히려 오류를 안 내서 불편한 나머지 const, let선언 전에 호출하면 에러를 내보내게 되었습니다.
    물론 에러는 내보내지만 호이스팅이 되지 않는 건 아니라는 점에 주의해야 합니다.


📝 개념 정리

호이스팅(Hoisting)은 스코프 내에서 변수 선언 및 함수 선언이 코드의 실행 단계 전에 스코프의 최상단으로 끌어올려지는 동작을 의미한다.
이는 자바스크립트의 컴파일링 과정에서 발생하며, 변수와 함수의 선언부만 끌어올려지고, 초기화나 할당은 끌어올려지지 않는다는 특징이 있다.

🌟 호이스팅이 발생하는 이유: 자바스크립트의 실행 과정

자바스크립트는 실행 전에 코드를 두 단계로 처리한다.

  1. 컴파일 단계: 변수를 선언하고, 함수 선언을 스코프의 최상단으로 이동(호이스팅)한다.
  2. 실행 단계: 코드를 위에서 아래로 읽으며 실행한다.

호이스팅은 컴파일 단계에서 발생하므로, 실행 전에 선언이 스코프의 맨 위로 이동된 것처럼 보이게 된다.


🌟 호이스팅의 적용 대상

호이스팅은 주로 아래와 같은 선언들에 적용된다.

  1. 변수 선언
    • var
    • let, const (단, 초기화 전 사용 시 에러 발생)
  2. 함수 선언: function
  3. 클래스 선언: 클래스도 호이스팅되지만, 초기화 전에 사용하면 에러 발생

🌟 호이스팅 동작 방식

  1. 변수 선언 (var)
    var로 선언된 변수는 선언이 호이스팅되지만, 초기화는 호이스팅되지 않는다.
    따라서 선언 전에 접근하면 undefined를 반환한다.

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

    내부 동작

    var a; // 선언이 호이스팅됨
     console.log(a); // undefined
     a = 5; // 초기화 및 할당 (초기화는 호이스팅되지 않음)
     console.log(a); // 5
  2. letconst
    letconst선언은 호이스팅되지만, 일시적 사각지대(TDZ: Temporal Dead Zone)에 의해 초기화 전에 접근할 수 없다.
    TDZ는 선언된 지점부터 초기화가 이루어질 때까지의 구간이다.

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

    내부 동작: let b;는 호이스팅되지만 TDZ에 의해 초기화 전 접근 불가

  3. 함수 선언 (function)
    함수 선언은 변수와 달리, 전체 함수 정의가 호이스팅된다.
    따라서 함수 선언 전에 호출할 수 있다.

    greet(); // "Hello, world!"
     function greet() {
       console.log("Hellow, world!");
     }

    내부 동작

    function greet() {
      console.log("Hello, world!");
    }
    greet(); // 함수 정의가 이미 호이스팅되었으므로 정상 호출 가능
  4. 함수 표현식 (var, let, const와 함께)
    함수 표현식은 호이스팅되지 않으며, 변수 호이스팅 규칙을 따른다.

    sayHello(); // TypeError: sayHello is not a function
     var sayHello = function () {
       console.log("Hi!");
     };

    내부 동작

    var sayHello;
     sayHello(); // sayHello는 undefined 상태임
     sayHello = function () {
       console.log("Hi!");
     };

🌟 클래스 선언

클래스 선언은 호이스팅되지만, 초기화 전에 접근하면 ReferenceError가 발생한다.

const obj = new MyClass(); // ReferenceError: Cannot access 'MyClass' before initialization
 class MyClass {
   constructor() {
     this.name = "JavaScript";
   }
 }

내부 동작: class MyClass 선언은 호이스팅되지만 TDZ가 적용된다.


🌟 호이스팅의 스코프

호이스팅은 선언된 스코프에 따라 다르게 동작한다.

  1. 전역 스코프: 전역 변수 및 함수 선언은 전역 객체(window 또는 globalThis)에 바인딩된다.
  2. 함수 스코프: 함수 내부에서 선언된 변수는 함수 내부에서만 호이스팅된다.
  3. 블록 스코프: let, const, 블록 내에서의 함수 선언은 해당 블록 내에서만 유효하다.

🌟 호이스팅의 정리

  1. var 변수: 선언은 호이스팅되지만 초기화는 호이스팅되지 않음(undefined 반환)
  2. letconst: 선언은 호이스팅되지만 초기화 전 접근 불가(TDZ 적용)
  3. 함수 선언: 전체 정의가 호이스팅되며 초기화 전 호출 가능
  4. 함수 표현식 및 화살표 함수: 변수 호이스팅 규칙에 따름
  5. 클래스 선언: 정의는 호이스팅되지만 초기화 전 접근 불가(TDZ 적용)

🌟 호이스팅을 이해하기 위한 예제

console.log(x); // undefined
console.log(y); // ReferenceError
console.log(z); // ReferenceError

var x = 10;
let y = 20;
const z = 30;

function foo() {
  console.log("Function foo");
}

foo(); // "Function foo"
bar(); // ReferenceError

var bar = function () {
  console.log("Function bar");
};

내부 동작

var x; // 호이스팅
let y; // 호이스팅 (TDZ)
const z; // 호이스팅 (TDZ)
function foo() {
  console.log("Function foo");
}
var bar; // 호이스팅

console.log(x); // undefined
console.log(y); // ReferenceError
console.log(z); // ReferenceError

x = 10;
y = 20;
z = 30;

foo(); // 정상 실행
bar(); // ReferenceError

bar = function () {
  console.log("Function bar");
};

🌟 결론 및 주의점

호이스팅은 코드의 동작을 예상하기 어렵게 만들 수 있으므로, 다음과 같은 권장 사항을 지키는 것이 좋다.

  1. letconst를 사용하여 TDZ를 활용한다.
  2. 변수 선언은 코드의 최상단에서 수행한다.
  3. 함수 표현식 대신 함수 선언문 또는 화살표 함수를 명확히 구분하여 사용한다.

이를 통해 호이스팅으로 인한 혼란을 줄이고, 코드를 더 읽기 쉽게 작성할 수 있다.

0개의 댓글