2 minute read

2022.09.22

💡 오늘의 JavaScript 공부

▶️ 호이스팅

변수 선언문이 코드의 선두로 끌어 올려진 것처럼 동작하는 자바스크립트 고유의 특징을 변수 호이스팅 이라고 한다.

자바스크립트는 함수가 실행되기 전 함수내의 필요한 변수값들을 모두 모아 유효범위 최상단에 선언한다.

📌 호이스팅의 대상

쉽게 말하자면

var 변수/ 함수선언문에서만 호이스팅이 일어난다.

let / const 변수 선언과 함수표현식에서는 호이스팅이 일어나지 않는다.

라고 보면 편할 것 같다 자세한 내용은 아래에서 다룰 예정

📌 간단한 예시
console.log(myname)    // undefined
console.log(myname2)   // ReferenceError

var myname = "kim se hoon"    // var변수
let myname2 = "kim se hoon2"  // let변수
------------------------------------------------
foo();       // "hello"     함수 선언문에서는 호이스팅이 일어난다. 
foo2();      // TypeError   함수 표현식에서는 호이스팅이 일어나지 않는다. 

function foo(){
  console.log("hello")    // 함수선언문
};
var foo2 = function(){
  console.log("hello2")   // 함수표현식
}

호이스팅은 함수선언문과 함수표현식에 서로 다르게 동작하기 때문에 주의해야 함.

📌 var, let, const의 호이스팅

변수는 3단계에 걸쳐 생성되는데 다음과 같이 나누어진다.

  1. 선언단계

    변수를 실행 컨텍스트의 변수 객체에 등록한다.

    이 변수 객체는 스코프가 참조하는 대상이 된다.

  2. 초기화 단계

    변수 객체에 등록된 변수를 위한 공간을 메모리에 확보한다.

    이 단계에서 변수는 undefined로 초기화 된다.

  3. 할당 단계

    undefined로 초기화된 변수에 실제 값을 할당한다.

👉 var 키워드 로 선언한 변수는 1단계와 2단계가 한번에 이뤄진다.

변수를 등록( 1단계 )하고 메모리에 변수를 위한 공간을 확보한 후, undefined로 초기화한다.

때문에 변수 선언문 이전에 변수에 접근하여도 스코프에 변수가 존재하기 때문에 undefined를 반환한다.

👉 let키워드 로 선언한 변수는 1단계와 2단계가 분리되어 진행된다.

스코프에 변수를 등록(선언 단계)하지만 초기화 단계는 변수 선언문에 도달했을 때(코드 실행 후) 이뤄진다.

따라서 아직 변수가 초기화되지 않았기 때문에 초기화 이전에 변수에 접근하려고 하면 참조 에러가 발생한다.

변수를 위한 메모리 공간이 아직 확보되지 않았기 때문이다. 따라서 스코프의 시작 지점부터 초기화 시작 지점까지는 변수를 참조할 수 없다.

👉 const키워드 로 선언한 변수는 선언 + 초기화 + 할당이 모두 한번에 이뤄진다.

📌 그렇다면 let , const는 정말로 호이스팅이 일어나지 않을까?

😱 정답은 NO‼️ 이다.

사실 let 과 const 도 호이스팅이 이루어진다.

📌 why? 그렇다면 왜 Error를 발생하는 것일까?

이것은 Temporal Dead Zone ( TDZ ) 때문이다.

console.log(name) // Error => Temporal Dead Zone

const name = 'sehoon' // 함수 선언 및 할당
console.log(name) // 사용가능 

let 과 const 는 TDZ의 영향을 받는다. 할당되지 않은 변수는 사용할 수 없다.

이는 코드를 예측 가능하게 하고 잠재적인 버그를 방지할 수 있다.

let age = 30;
function showAge(){
  console.log(age);
}
showAge();  // 30 
-------------------------------------------------
// Error ex)
let age = 30;
function showAge(){    // Temporal Dead Zone
  console.log(age);    // Temporal Dead Zone
  let age = 20;       //  Temporal Dead Zone
}
showAge(); // Reference Error
// 호이스팅은 Scope단위로 일어난다. 

여기서 알 수 있는 점은 위에서 말했듯 let은 선언단계와 초기화단계가 분리되어 발생한다

즉, let은 호이스팅 되면서 선언단계가 이루어지지만 초기화단계는 코드에 도달했을 때 일어나기 때문에 Reference Error가 발생한다는 것을 알 수 있다.

📌 마무리

코드의 가독성과 유지보수를 위해서는 최대한 호이스팅이 일어나지 않도록 해야 한다.

Comments