만자의 개발일지

[JavaScript] 호이스팅이란 본문

JavaScript

[JavaScript] 호이스팅이란

박만자 2022. 3. 16. 19:06

호이스팅에 들어가기 앞서 먼저 자바스크립트에서 어떻게 변수를 생성하는지에 대해 이해할 필요가 있습니다.

 

자바스크립트에서의 변수 처리

자바스크립트에서는 총  3단계에 걸쳐 변수를 생성합니다.

  1. 선언 단계(Declaration phase)
    • 변수 객체(Variable Object)를 생성하고 변수를 등록한다.
    • 스코프는 해당 변수 객체를 참조한다.
  2. 초기화 단계(Initialization phase)
    • 변수 객체(Variable Object)에 등록된 변수를 메모리에 할당한다.
    • 변수는 undefined로 초기화된다.
  3. 할당 단계(Assignment phase)
    • undefined로 초기화된 변수에 실제값을 할당한다.

자바스크립트에서는 var, let, const 키워드를 붙여 변수를 생성합니다.

이는 기본적으로 3단계를 거쳐서 실행되지만 실행되는 순서가 조금씩 다릅니다.

 

let, const

let의 경우 선언 단계와 초기화 단계가 분리되어 있고 그 사이에 TDZ가 존재합니다. 이 TDZ에 접근할 경우 Reference Error가 발생하게됩니다.const의 경우 let과는 달리 선언 단계와 초기화 단계가 동시에 실행됩니다. 하지만 그전에 TDZ가 생성되어 TDZ에 접근할 경우 역시 Reference Error를 발생합니다.

console.log(value) // Declaration phase -> TDZ
let value = 'Hello World' // Initialization phase -> Assignment phase

// ReferenceError: Cannot access 'name' before initialization
console.log(value) // TDZ
const value = 'Hello World' // Declaration phase -> Initialization phase -> Assignment phase

// ReferenceError: Cannot access 'name' before initialization

 

var

var는 let, const와 달리 TDZ가 존재하지 않습니다. 

var는 선언 단계와 초기화 단계가 동시에 진행되며 선언과 동시에 undefined로 초기화됩니다.

console.log(value) // Declaration phase -> Initialization phase 
var value = 'Hello World' // Assignment phase

// undefined

 

var과 let,const의 차이는 TDZ의 유무입니다.

여기서 TDZ(Temporal Dead Zone)은 스코프 혹은 라이프 사이클의 시작지점부터 초기화 단계 직전까지의 구간을 의미합니다.

 

호이스팅(Hoisting)

호이스팅이란 스코프(함수) 안에 존재하는 모든 선언들을 해당 스코프(함수)의 최상단으로 끌어올리는 것을 말합니다.자바스크립트 엔진은 코드를 실행하기 전에 실행 가능한 코드를 형상화하고 구분하는 과정을 거칩니다.이 과정에서 자바스크립트 엔진은 코드 실행을 위한 모든 선언들을 스코프에 등록(메모리에 저장)합니다. 

 

호이스팅의 대상은 두가지가 있습니다.

  • variable declaration(변수 선언)
  • function declaration(함수 선언)

여기서 중요한 점은 선언에만 호이스팅이 일어난다는 점입니다.

선언에서만 호이스팅이 일어나기 때문에 값을 할당하더라도 할당된 값은 호이스팅이 일어나지 않습니다.

이는 위  let, const 예제에서 Reference Error가 발생하는 이유이기도 합니다.

console.log(value) // undefined 
var value = 'Hello World'

// 해당 코드에서 var가 에러가 나지 않는 이유는 값이 할당되진 않지만 선언과 동시에 undefined로 값이 초기화 되어있기 때문

꽤 많은 분들이 var는 호이스팅이되고 let, const는 호이스팅이 되지 않는다 라고 생각하시는데, let과 const도 호이스팅은 됩니다. 

다만 아무런 값이 할당이 되어있지 않기 때문에 에러가 나는 것 뿐입니다.

 

변수 선언에 대해서는 위에서 알아보았으니 이제 함수를 선언했을 때 어떻게 동작하는지 알아보도록 하겠습니다.

 

함수 선언에서의 호이스팅

 

함수 선언의 경우 선언 단계, 초기화 단계, 할당 단계를 동시에 진행합니다.

때문에 TDZ도 존재하지 않습니다.

 

아래 함수 선언식으로 생성된 fun1함수와 함수 표현식으로 생성된 fun2함수가 있습니다.

fun1함수의 경우 제대로 호출되지만 fun2함수의 경우 함수가 할당되지 않은 것을 볼 수 있습니다.

앞서 설명했다 시피 호이스팅은 선언만 스코프(함수)의 위로 끌어올리기 때문에 함수를 할당 할지라도 할당한 값은 호이스팅 되지 않기 때문에 다음과 같이 에러가 나는 것입니다.

fun1()
fun2()

function fun1() {
    console.log(value)
    var value = 'Hello World'
}

var fun2 = function() {
    console.log(value)
    var value = 'Hello World'
}

// undefined
// TypeError: fun2 is not a function

 

결론

  • var, let, const 모두 호이스팅된다.
  • 의도치 않은 동작을 방지하기 위해 var 대신 let 사용을 지양하자.

 

 

참고

 

 

 

'JavaScript' 카테고리의 다른 글

[JavaScript] 콜백함수(Callback Function)란  (0) 2022.03.17
[JavaScript] Private Method 와 Field  (0) 2022.03.16
[JavaScript] for문 정리  (0) 2022.03.16
[JavaScript] 생성자와 프로토타입  (0) 2022.03.15
[Javascript] 변수 선언  (0) 2021.06.01
Comments