Javascript 호이스팅

이지훈·2021년 12월 14일
1

공부한것들

목록 보기
14/15

공부하기전

this 키워드와 함께 자바스크립트에서 가장 많이 보는 단어 중 하나가 호이스팅이다. 어느정도는 알고 있었지만 잘 몰랐던 부분이나 특히 잘못 알고 있던 부분도 많아 정리하는게 많은 도움이 되었다.
기본적인 호이스팅의 개념은 MDN을 많이 참고했다.
그리고 함수와 변수 호이스팅의 차이, JS실행과 호이스팅의 연관성에 대해서는 테코블의 호이스팅에 대한 오해와 진실 페이지를 많이 참고했다.

호이스팅이란

Javascript에서 인터프리터가 변수와 함수의 메모리 공간을 선언 전에 미리 할당해두는것을 호이스팅(hoisting)이라고 한다.
이로인해 나타나는 변수,함수의 선언부가 위치한 인접 스코프의 시작 지점에서 해당 식별자의 관측이 가능한 현상까지 호이스팅이라고 말할 수 있겠다.

이전에 알아본 것 처럼 JS는 코드를 실행하기 위해 컴파일 과정을 거치게 되는데, 이 과정에서 JS엔진이 모든 스코프 또는 실행 컨텍스트를 탐색하며 여러 변수 객체에 식별자를 수집한다. 이렇게 실행 시점으로 넘어가기 전에 선언된 식별자에 대한 정보를 이미 알고 있기 때문에 선언 이전에 참조할 수 있게 되는것이다.

호이스팅의 대상

원래는 var과 function만 호이스팅의 대상이 된다고 알고 있었는데 실제론 조금 달랐다.
호이스팅을 초기화까지 포함하지 않고, 인접 스코프 상단에서 선언부를 관측할 수 있는 현상 이라고 생각한다면 var, function 키워드 뿐만 아니라 let과 const 또한 호이스팅의 대상으로 볼 수 있다.

var로 선언한 변수는 호이스팅시 undefined로 변수를 초기화한다. 반면 let과 const로 선언한 변수는 호이스팅시 변수를 초기화하지 않는다.
그래서 선언 이전에 사용하려고 했을 때 var로 선언한 변수는 undefined가 출력되고 let,const로 선언한 변수는 에러가 뜨는 것이다.

함수와 변수 호이스팅

호이스팅은 함수와 변수로 나눌수 있는데, 이 때 함수는 함수선언으로 작성된 경우를 말한다.

함수선언

function calcRectArea(width, height) {
  return width * height;
}
console.log(calcRectArea(5, 6));
// expected output: 30

함수표현식

const getRectArea = function(width, height) {
  return width * height;
};
console.log(getRectArea(3, 4));
// expected output: 12

함수표현식의 경우 결국 변수에 함수를 할당하는 형태여서 변수 호이스팅에 해당한다.

함수 호이스팅

함수 호이스팅이 가장 먼저 이루어진다. 함수의 선언문은 식별자가 변수 객체에 수집될 때 부가적으로 함수의 참조에 대한 초기화까지 자동으로 이루어지기 때문에 상단에서 참조, 호출이 가능하다.

변수 호이스팅 (+ 변수의 선언, 초기화, 할당)

변수의 상태 - 선언, 초기화, 할당

  1. 선언: 파싱 과정에서 변수 객체가 변수에 대한 식별자들을 수집한다. 식별자를 남기는 단계.
  2. 초기화: 선언한 구문에서 일어나며 변수에 값을 할당하고 접근가능하게 한다. var의 경우는 호이스팅 단계에서 undefined로 초기화된다.
  3. 할당: 변수 안에 값을 저장한다. 할당 구문인 =을 사용한다. 변수의 첫번째 할당문이 초기화이다.

우선 변수가 선언, 초기화, 할당 세가지 단계를 거친다는 것을 알게 되었는데 이중 초기화와 할당의 차이를 잘 알지 못해 조금 더 검색을 해 보았다. 참고-stackoverflow 문답

위 페이지를 참고하면,

{ // declaration (hoisted)
  // Temporal deadzone
  let foo; // declaration and initialization to undefined
  foo = 1; // assignment
}

호이스팅을 통해 선언이 스코프 최상단에서 일어난다. 그리고 실제 선언문은 let foo;에서 일어나며, 이 때 undefined초기화된다. 그리고 그 아래에 foo = 1;에서 할당이 되며 변수에 값이 저장된다.

let foo;는 foo를 undefined로 초기화할것이고,
let foo = 1;은 foo를 1로 초기화할것이다.

! const는 값을 할당하지 않고 선언만 하는것이 불가능하다(const foo;이런식으로)

Temporal DeadZone(TDZ)

그리고 스코프의 시작과 함께 호이스팅을 통해 변수 foo가 선언되기는 하지만 let, const의 경우 undefined로 초기화되지않기때문에 실제 선언문 이전까지는 참조가 불가능하다(참조시 레퍼런스 에러). 이 시작부터 선언문 이전까지의 구간을 일시적 사각지대, Temporal DeadZone(TDZ)이라고 한다.

규칙성

앞서 살펴본 함수, 변수의 호이스팅 과정을 정리하여 규칙을 나타내본다면 다음과 같다.

  • 선언된 함수는 선언문 상단에서 참조, 호출이 가능하다.
  • var로 선언된 변수는 선언문 상단에서 참조, 할당이 가능하다.
  • let, const로 선언된 변수는 상단에서 참조, 할당이 불가능하다.

도움. 출처

profile
안녕하세요! 대학교 졸업한 이지훈입니다.

0개의 댓글