Javascript의 호이스팅

Hyeongmin·2024년 4월 11일

 TIL (Today I Learned)

목록 보기
54/54

호이스팅(Hoisting) 이란?

"호이스팅"이라는 용어는 글자 그대로 "끌어올리다"라는 뜻을 갖고 있다. JavaScript에서는 변수 선언과 함수 선언을 컴파일 단계에서 메모리로 끌어올리는 현상을 호이스팅이라고 한다. 이는 코드 실행 이전에 선언된 변수나 함수가 메모리에 할당되어 있어 마치 코드 상단에 선언한 것처럼 동작하게 된다.


함수 호이스팅

함수 호이스팅은 JavaScript에서 함수 선언이 해당 스코프의 최상단으로 끌어올려지는 현상을 말한다. 이것은 함수 선언이 실제 코드의 위치와 관계없이 스코프 내 어디서든 호출될 수 있음을 의미한다.

예를 들어, 다음 코드를 살펴보자.

foo(); // "Hello, world!"  // 함수 호출

function foo() {   // 함수 선언
  console.log("Hello, world!");
}

위의 코드에서 foo 함수가 선언되기 전에 함수 호출이 나타나지만, 함수 호출이 정상적으로 작동한다. 이것이 함수 호이스팅의 결과이다. JavaScript는 함수 선언을 스코프의 최상단으로 끌어올리기 때문에 함수가 선언되기 전에 호출되어도 오류가 발생하지 않는다.

그러나 함수 표현식은 호이스팅되지 않는다. 함수 표현식은 변수에 할당된 함수를 의미하며, 변수는 호이스팅되지만 할당된 함수는 호이스팅되지 않는다.

bar(); // TypeError: bar is not a function

var bar = function() {
  console.log("Hello, world!");
};

위의 코드에서는 변수 bar가 호이스팅되지만 함수가 할당되지 않았으므로 TypeError가 발생한다. 함수 표현식은 선언되기 이전에 호출되었을 때 호이스팅이 발생하지 않으므로 주의해야 한다.

변수 호이스팅

var로 선언한 변수 호이스팅

변수 호이스팅은 var, let, const 선언 방식에서 모두 발생한다.

변수가 호이스팅 될 때, 선언과 초기화가 호이스팅되지만 할당은 호이스팅되지 않는다. var 키워드로 선언된 변수는 선언부만 호이스팅되고 초기화는 undefined로 이루어진다. 따라서 변수가 선언되기 전에 사용되면 JavaScript는 undefined를 반환한다. 이는 변수가 선언되었지만 값을 할당받지 않았기 때문이다.

예를 들어, 다음과 같은 코드가 있다고 가정해보자.

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

위 코드에서는 myVar 변수가 선언되기 전에 사용되었다. 그러나 JavaScript는 선언된 변수를 먼저 확인하고, 선언되어 있지만 값이 할당되지 않은 경우를 undefined로 처리한다. 따라서 위의 코드는 오류 없이 실행되며, undefined가 출력된다. 변수가 호이스팅되어 선언부만 먼저 처리되었기 때문에 이러한 결과가 나타난다.

let과 const로 선언한 변수 호이스팅

let과 const는 호이스팅이 발생하지만, var와는 동작 방식이 다르다.
let과 const는 블록 스코프 변수로서, 선언되기 전에 접근하면 ReferenceError(참조 에러)가 발생한다. 하지만 호이스팅은 발생하기 때문에 블록 내에서 선언 전에 해당 변수를 사용하면 undefined가 아닌 ReferenceError가 발생합니다. const는 변수에 재할당할 수 없으며, 선언과 동시에 값을 할당해야 한다. let은 변수를 선언할 때 초기값을 주지 않아도 되지만, 사용하기 전에는 반드시 값을 할당해야 한다.

예를 들어, 다음과 같은 코드를 살펴보자.

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

이 코드에서는 변수 myVar를 선언하기 전에 해당 변수를 참조하려고 시도하고 있다. 이 때 let 키워드로 변수를 선언했기 때문에 호이스팅은 발생하지만, 초기화가 이루어지기 전까지 변수에는 액세스할 수 없다. 이렇게 선언 전에 접근하면 참조 에러(ReferenceError)가 발생합니다. 이는 변수가 존재하지 않기 때문에 발생하는 오류이다.

JavaScript에서 let과 const 키워드로 변수를 선언하면 TDZ(Temporal Dead Zone)가 생성된다.
TDZ는 "Temporal Dead Zone"의 약자로, 임시적인 사각지대를 의미한다. TDZ는 let 및 const로 선언된 변수가 실제 선언되기 전까지 액세스할 수 없는 영역을 나타낸다. 이는 변수가 호이스팅되지만 초기화되기 전까지는 사용할 수 없음을 의미한다. TDZ는 변수가 선언된 위치부터 선언이 실행되는 지점까지의 영역을 가리킨다. 만약 TDZ에서 변수에 접근하려고 하면 참조 에러가 발생한다.
이를테면

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

이 코드에서 myVar 변수에 접근하려고 하지만, 해당 변수가 초기화되기 전에 액세스하려고 하기 때문에 TDZ에 들어가 참조 에러가 발생한다.

0개의 댓글