카테고리 없음

[JS] 호이스팅

Hosae905 2024. 9. 4. 00:52

호이스팅(Hoisting)


자바스크립트에서 호이스팅이란 인터프리터가 코드를 실행하기 전에 함수, 변수, 클래스 또는 import 선언문을 해당 범위의 맨 위로 끌어올리는 것처럼 보이는 현상을 의미한다.

개발자가 어느 라인 위치에 코드를 선언해도 실행되기 전 코드가 최상단으로 끌어올려지고 실행되게 된다.

이러한 호이스팅이 발생하는 원인은 자바스크립트의 변수 생성과 초기화의 작업이 분리돼서 진행되기 때문이다.

그럼 호이스팅이 어떤 상황에서 발생하는지 알아보자.

 

호이스팅이 발생되는 상황


  • 변수의 호이스팅

간단한 예제를 통해서 호이스팅이 발생하는 상황을 살펴보자.

// 이렇게 코드를 작성하면 1번 코드에서 undefined가 출력된다.
console.log(name)   // 1
var name = 'test'
console.log(name)   // 2

위의 예제 코드와 같이 첫번째 라인에서 name을 출력하고 있는 것을 확인할 수 있지만 자세히 생각해 보면 name이라는 변수는 아직 생성되지 않은 변수인데 첫 번째 라인에서 console.log를 통해 undefined가 출력된다.

var name
console.log(name)
name = 'test'
console.log(name)

호이스팅이 발생하는 코드를 자세히 풀어보면 위의 코드와 같이 변수의 선언과 초기화 작업이 분리돼서 실행된다.

먼저 var name이 호이스팅되어 맨 위의 라인으로 끌어올려져 실행된다. 그 후 console.log(name)을 하면 undefined가 출력되고 그다음으로 name에 test라는 값을 저장한 뒤 다시 출력해 보면 그제야 test가 출력된다.

예제를 통해 알 수 있는 것은 변수가 선언된 라인 이전에 해당 범위에서 변수 값을 사용하는 경우 호이스팅이 된다는 것을 알 수 있다.

또한, 변수가 선언된 라인 이전에 해당 범위의 변수를 참조할 수 있지만 신기하게도 ReferenceError를 던지지 않고 값이 항상 undefined이 출력된다.

이러한 변수 호이스팅은 var 키워드를 사용했을 때 발생할 수 있다.

그렇다면 es6로 넘어오면서 새롭게 생긴 let과 const 키워드는 호이스팅이 안되는 것일까?

console.log(name)
let name = 'test'
console.log(name)

앞서 진행했던 var 키워드를 사용한 호이스팅 예제와 똑같이 작성한 예제로 키워드만 let으로 변경해 주었다.

위의 코드를 실행하면 var 키워드와 마찬가지로 호이스팅이 되는 것을 알 수 있다.

하지만 출력 결과에 대해서 var 키워드와 큰 차이점을 가지는데 바로 undefined가 아닌 아래와 같은 ReferenceError를 출력한다는 점이다.

ReferenceError: Cannot access 'name' before initialization

여기서 헷갈렸던 부분이 있었는데 let과 const 키워드가 호이스팅이 된다는 것을 어떻게 알 수 있는지였다.

그에 대한 해답은 let과 const를 사용하여 출력되는 에러를 통해서 알 수 있었다.

이전에 var 키워드는 undefined를 통해서 호이스팅이 발생했다는 것을 알았다. 위의 ReferenceError도 자세히 보면 name이라는 변수가 초기화되지 않았다는 것을 알려주는데 즉, name은 초기화가 되지 않은 undefined 상태라는 것을 알 수 있다.

변수의 호이스팅을 공부해 보면 왜 개발자들이 let과 const 키워드를 권장하는지 알 수 있다.

해당 키워드를 사용함으로써 호이스팅은 되지만 초기화를 하기 전까지 변수에 접근하면 에러를 발생하여 예상치 못한 동작을 일으킬 수 없도록 막을 수 있다.

 

  • 함수의 호이스팅

호이스팅은 변수 외에도 함수에서도 발생할 수 있다.

기본적으로 함수를 정의하는 문법으로는 함수 표현식과 함수 선언식이 있다.

먼저 함수 선언식을 살펴보자.

console.log(add(2, 3));

function add(x, y) {
    return x + y;
}

console.log(add(2, 3));

위의 예제 코드와 같이 함수 선언식을 작성하여 실행해 보면 호이스팅이 되는 것을 확인할 수 있다.

첫 번째 라인에서 add(2, 3)은 아직 add라는 함수가 정의되지 않았음에도 불구하고 add 함수를 호출하여 연산을 진행한 결과인 5를 출력해 준다.

// 함수 선언식 호이스팅
function add(x, y) {
    return x + y;
}

console.log(add(2, 3));
console.log(add(2, 3));

이것이 가능한 이유는 위의 코드와 같이 호이스팅으로 인해 add 함수가 최상단으로 끌어올려졌기 때문이다.

 

console.log(result(2, 3));

const result = function (x, y) {
    return x + y;
};

console.log(result(2, 3));

다음으로 함수 표현식을 살펴보면 위의 코드와 같다. 말 그대로 함수를 정의해 변수에 저장하여 표현해 주는 것이다.

위와 같이 함수 표현식 형태로 함수를 정의하게 되면 함수 선언식과 다르게 첫 번째 라인의 console.log(add(2,3)) 코드에서 ReferenceError: Cannot access 'result' before initialization 에러가 발생하게 된다.

함수를 호출한다는 점만 보면 함수 선언식을 사용해도 이상할 게 없다는 생각이 든다. 하지만 호이스팅이 된다는 것만으로도 코드의 구조가 예상치 못하게 동작할 수 있는 가능성을 열어두는 것 같아 되도록 함수 표현식을 사용하는 것이 좋을 것 같다고 생각한다.

 

참고 자료


 

호이스팅 - MDN Web Docs 용어 사전: 웹 용어 정의 | MDN

JavaScript 호이스팅은 인터프리터가 코드를 실행하기 전에 함수, 변수, 클래스 또는 임포트(import)의 선언문을 해당 범위의 맨 위로 끌어올리는 것처럼 보이는 현상을 뜻합니다.

developer.mozilla.org

 

 

📚 호이스팅(Hoisting) 발생 원리를 알아보자

자바스크립트 호이스팅(Hoisting) 자바스크립트에서 호이스팅(Hoisting)은 변수 선언과 함수 선언을 코드의 맨 위로 끌어올려지는 현상을 일컫는다. 그래서 개발자가 어느 라인 위치에 코드를 선언

inpa.tistory.com

 

Hoisting in JavaScript with let and const – and How it Differs from var

I used to think that hoisting only happened to variables declared with var. But recently, I learned that it also happens to variables declared with let and const. I'll explain what I mean in this article. I also have a video version of this article [https:

www.freecodecamp.org