[자바스크립트] 호이스팅
미음제
·2022. 3. 4. 21:35
호이스팅(Hoisting)
호이스팅(hoisiting)이란 자바스크립트 엔진이 변수와 함수의 메모리 공간을 선언하기 이전에 미리 할당하는 것을 의미한다. 흔히 호이스팅에 대해 말할 때, "변수와 함수의 선언을 해당 범위(Scope) 최상단으로 올리는 것."이라고 말을 하는데 정확한 표현은 아니다. 정확히는 그렇게 보이는 현상을 말한다.
자바스크립트 엔진은 코드를 실행하기 전에 코드를 먼저 살펴본다고 생각하면 된다. 자바스크립트 엔진은 코드를 실행하기 전에 실행 가능한 코드를 형상화하고 구분하는 과정을 거친 후, 실행하기 전에 모든 선언을 범위(Scope)에 등록한다. 이 과정을 통해 메모리에 미리 할당해 두었기 때문에 선언문보다 호출이 앞서도 에러 없이 동작이 가능하다. 다른 언어에서는 당연히 에러를 발생하지만, 이 덕분에 자바스크립트는 에러 없이 동작할 수 있게 된다. (정확히는 var만 해당된다고 하는데, 이 부분에 대해서는 추후에 공부를 제대로 하고 다시 업로드), (var로 선언한 변수는 undefined으로 초기화)
var num = 11;
console.log(num); // 출력 결과 : 11
num이라는 변수를 선언하고 11이라는 값을 저장했다. 그리고 num이라는 변수를 출력하면 당연히 11이 출력된다. 그러나 num이 선언되기 전에 호출을 먼저 하게 되면 어떻게 될까?
console.log(num); // 출력 결과 : undefined
var num = 11;
console.log(num); // 출력 결과 : 11
에러가 발생할 것 같지만, 자바스크립트에서는 에러가 발생하지 않는다. 결과는 undefined가 출력된다. 자바스크립트 엔진은 코드가 실행되기 전에, 코드를 쭉 훑어보고 선언된 변수나 함수들을 미리 확인한다. 미리 확인한 후, 해당 변수와 함수를 메모리에 먼저 할당한다. 그리고 호출이 되었을 때 메모리에 할당된 선언을 호출해 준다. 호이스팅 시 변수의 선언과 동시에 초기화를 진행한다. num 이라는 변수가 선언되고 undefined로 초기화 된 것이고, 이 때 호출이 되어서 undefined가 출력된 것이다. 이후에 값 할당을 11로 하고 출력한 결과는 11이 출력된 것이다.
함수 또한 선언 이전에 호출을 하더라도 동작하게 된다.
function hello(name) {
console.log(`Hello, ${name}!`);
}
hello('MJ'); // 출력 결과 : Hello, MJ!
일반적으로 작성된 코드의 순서가 위와 같다면, 함수를 선언하기 이전에 호출하게 된 코드는 다음과 같다.
hello('MJ');
function hello(name) {
console.log(`Hello, ${name}!`);
}
// hello('MJ');
이 경우에도 에러가 발생하지 않고 정상적으로 코드가 작동하게 된다.
let, const 호이스팅
var 변수를 호이스팅 한 것과 같은 예제를 let으로 작성하면 다음과 같다.
console.log(num);
let num = 1;
var의 경우였을 때, 출력 결과는 undefined였다. 그러나 let의 경우는 에러가 발생하게 된다.
num이라는 변수를 호출할 때, 선언(초기화)되지 않은 변수에 접근하려 했기 때문에 에러가 발생한 것이다. let, const로 선언한 변수도 호이스팅 대상이지만, var와 다르게 undefined로 초기화하지는 않기 때문에 변수의 초기화를 하지 않고 호출을 하게 되면 예외가 발생하는 것이다.
호이스팅 규칙
호이스팅을 간단히 이해하기 위해 요약하자면 다음과 같다.
- 선언된 변수와 함수는 상단에서 호출이 가능
- var로 선언된 변수와 함수는 상단에서 호출이 가능
- let, const로 선언된 변수는 상단에서 호출이 불가능
let, const는 호이스팅이 발생하면 '선언'만 동작하고 호출 시점에서 진짜 선언을 한 곳을 만나기 전까지 초기화가 진행되지 않는다. 이 사이만큼 변수에 대한 메모리는 할당되어 있지 않기 때문에 선언보다 앞서 호출이 불가능한 것이다.
이를 잘 이해하기 위해서는 let의 '시간상 사각지대(TDZ, Temporal Dead Zone)를 참고해야 한다.
프로그래머스 데브코스 코딩 테스트에 합격하고 지난 28일에 화상 면접을 보게 되었다. 5명(필자 포함)의 지원자와 면접관 간에 편한 대화 속에서 지원서 위주의 면접이 진행되었다. 면접 후반부 쯔음 개인 질문에서 호이스팅과 클로저에 대한 질문을 받았다. 우아한테크코스를 지원하면서 자바스크립트를 접하게 되었고, 과제를 진행하기 위해 자연스럽게 학습을 시작했다. 과제를 진행하던 중 친구중에 프론트엔드 분야로 SAFFY를 수료한 친구가 있어, 호이스팅과 클로저에 대해 물어봤던 기억이 있다. 당시에 문법적인 이해가 급급했던 터라 답변을 대충 듣고 넘겼었다. 추후에 클로저를 다룰 때, 더 깊은 공부를 할 때 찾아보자는 생각만 하고 나중으로 미뤘었는데, 면접 때 질문을 받고 적잖이 당황했었다.
질문을 받고 "최상단으로 끌어올리는 것입니다."라고 대답하고 싶었지만, 정확한 답변이 아닌 거 같았고, 순간 생각이 나지 않았었다. 지금 작성한 내용도 깊은 이해를 바탕으로 작성하진 못했다. 큰 틀에서 이해를 먼저 했고, 다음에 깊이 공부를 하고 작성한 글을 수정해야 한다. let과 var의 차이도 범위(Scope)의 차이로만 알고 있었는데 이 부분에 대한 학습도 필요하다.
'Developer > Javascript' 카테고리의 다른 글
[자바스크립트] sort() (0) | 2022.02.18 |
---|---|
[자바스크립트] filter(), reduce() (0) | 2022.02.18 |
재귀 함수와 스택 프레임(Stack Frame) (0) | 2022.02.16 |
[자바스크립트] 생성자 함수, 객체 생성 (0) | 2021.12.03 |
[Chart.js] Chart.js로 차트 그리기 (1) | 2021.04.24 |