[LG CNS AM Inspire Camp 1기] FE - 호이스팅(Hoisting)🌟

이슬아·2025년 1월 2일

호이스팅(Hoisting)이란?

호이스팅은 간단히 말해 변수나 함수, 클래스 또는 임포트(import)의 선언문을을 코드 맨 위로 끌어올리는 것처럼 동작하는 매커니즘이다.
하지만 실제로 코드가 물리적으로 이동하는 건 아니고, 자바스크립트 엔진이 실행 전에 코드를 스캔하면서 변수와 함수 선언을 미리 처리하여 메모리에 등록한다.

1️⃣ 변수 호이스팅

📍 var

선언만 맨 위로 올라가고, 값은 undefined로 초기화

console.log(x1);        // undefined => x1 변수가 hoisting되어 선언된 것으로 처리
var x1;  
console.log(x1);        // undefined

console.log(x2);    // undefined
var x2 = 100;
console.log(x2);    // 100

내부적으로 아래와 같이 해석되어 실행

var x1;  
console.log(x1);        // undefined
console.log(x1);        // undefined

var x2;
console.log(x2);    // undefined
x2 = 100;
console.log(x2);    // 100

📍 let,const

선언만 올라가지만 초기화되지 않아서 사용하려면 ReferenceError 에러 발생

❗️하지만 ReferenceError 에러가 발생했다고 호이스팅이 되지 않았다고 생각하면 안된다.

let과 const는 호이스팅 되어 변수를 메모리에 올려두었지만, 초기화 되지 않은 상태로 일시적 사각지대(TDZ, Temporal Dead Zone)에 머물러 있어 선언한 코드 줄을 지나야 접근 가능한 상태이다.

TDZ란?
쉽게 말해서 선언만 되고 아직 초기화 되지 않는 변수가 머무는 공간

console.log(x3);    // Cannot access 'x3' before initialization
let x3 = 100;
console.log(x3);    // 100

내부적으로 아래와 같이 해석되어 실행

let x3;             // 변수 선언이 호이스팅되지만 초기화되지 않음 
                    // ⇒ TDZ 본관 ⇒ 초기화되기 전에 참조할 수 없음 		
console.log(x3);    // Cannot access 'x3' before initialization
x3 = 100;
console.log(x3);    // 100

2️⃣ 함수 호이스팅

함수 선언문 vs 함수 표현식

function hello() { // 함수선언문
        console.log("Hello");
}

var world = function() { // 함수 표현식
  console.log("World");
}

var nice = () => { // 함수 표현식 (화살표 함수)
  console.log("Nice to Meet You!");
}

-> 다음 장에서 더 자세히 다룰 것

함수 선언문

  • 함수 선언문 형식으로 함수를 정의하면 함수 정의 부분이 호이스팅되어 위치와 관계 없이 호출이 가능하다.
  • 완전히 호이스팅 → 선언 전에도 호출 가능
hello();        // Hello, JavaScript

// 함수 선언문 형식으로 정의
function hello() {
console.log("Hello, JavaScript");
        }

함수 표현식

  • 함수 표현식으로 함수를 정의하는 경우, 함수 변수 선언 방식에 따라 오류가 발생한다.
  • 변수의 규칙을 따름

📍 var

hello();        // Uncaught TypeError: hello is not a function
       
var hello = function() {
console.log('Hello, JavaScript!');
        };
hello();        // Hello, JavaScript!

위 코드는 아래와 같이 해석

var hello;      // undefined 상태
hello();        // Uncaught TypeError: hello is not a function
       
hello = function() {
console.log('Hello, JavaScript!');
        };
hello();        // Hello, JavaScript!

📍 let,const

 hello();        // Uncaught ReferenceError: Cannot access 'hello' before initialization
       
let hello = function() {
console.log('Hello, JavaScript!');
        };

위 코드는 아래와 같이 해석

let hello;      // 초기화되기 전까지 TDZ(Temporal Dead Zone)에 머물러 있다.
       
hello();        // Uncaught ReferenceError: Cannot access 'hello' before initialization
       
hello = function() {
console.log('Hello, JavaScript!');
        };

✚ var, let, const의 차이점은?

var

  • 호이스팅 : undefined
  • 같은 스코프 내에서 변수의 재선언과 재할당이 가능 (중복 선언 허용)
  • var로 선언된 변수는 함수 스코프를 따른다.
    즉, 함수 내에서 선언된 변수는 함수 전체에서 접근 가능하다는 것으로, 블록(if,for)내부에서 변수가 선언된 경우에에도 블록 외부에서 접근이 가능해진다.
function example() {
  if (true) {
    var x = 10;
  }
  console.log(x); // 10
}
example();

위 코드에서 if 블록 내부에서 선언된 변수 x는 함수 스코프를 따르기 때문에 블록 외부에서도 접근 가능하게 된다.
이것은 때로 의도치 않은 오류를 초래할 수 있다.

function example() {
  var = x = 1
  if (true) {
    var x = 10; //기존 x를 덮어씀
  }
  console.log(x); // 10
}
example();

🔥var는 ES6 이전에 사용되던 변수 선언 방식으로, 현재는 의도치 않은 오류를 유발하여 사용이 권장 않고 대신 let과 const 사용을 권장한다.

let

  • 호이스팅: ReferenceError 발생
  • 같은 스코프 내에서 변수의 재선언은 불가능하지만, 재할당은 가능
  • 블록 스코프를 가진다.
    즉, {}블록 내에서 선언된 변수는 해당 블록 내에서만 유효하다.

🔥 값이 변경될 수 있는 변수를 선언할 때 사용한다.
예를 들어, 반복문에서 인덱스 변수나 조건에 따라 값이 변하는 변수를 선언할 때 적합하다.

const

  • 호이스팅: ReferenceError 발생
  • 같은 스코프 내에서 변수의 재선언과 재할당이 모두 불가능하다.
  • 블록 스코프를 가진다.

🔥 값이 변경되지 않는 상수를 선언할 때 사용한다.
객체나 배열을 const로 선언하면 참조 자체는 변경할 수 없지만, 내부의 프로퍼티나 요소는 변경이 가능하다.

0개의 댓글