Hoisting

zioo·2021년 12월 20일
0

Backend

목록 보기
7/40

Hoisting

호이스팅은 코드가 실행하기 전 변수선언/함수선언이 해당 스코프의 최상단으로 끌어 올려진 것 같은 현상


JS 엔진은 스크립트를 가져 오면 가장 먼저 코드에서 데이터를 위한 메모리를 설정한다. 이 시점에는 코드가 실행되지는 않고 실행을 하기 위한 준비단계이다.

함수와 변수가 메모리에 저장되는 방식은 다르다.

  • 함수는 전체 함수에 대한 참조와 함께 저장된다.
  • 변수의 경우 ES6 문법인 let과 const는 초기화 되지 않은 채로 저장이 되고, var는 undefined로 저장이 된다.
console.log(sum(2,3));
console.log(name);
console.log(age);

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

const name = 'hoo00nn';

var age = 25;

어떻게 동작할까 ?

먼저 첫 번째 console.log를 살펴보겠다.
함수는 전체 함수의 대한 참조와 함께 메모리에 저장되기 때문에 함수를 만든 라인 이전에도 호출할 수 있다.

두 번째 console.log를 보겠다.
const는 초기화되지 않은 채로 메모리에 저장이 되기 때문에 초기화 전에 변수를 참조할 수 없다는 ReferenceError 가 발생한다.

세 번째 var의 경우를 보겠다.
var는 undefined 형태로 메모리에 저장이 되기 때문에 undefined가 콘솔에 찍힌다.

변수의 값은 언제 할당될까?

그럼 언제 값이 할당되는 것일까?

답은 간단하다. 코드가 한줄 한줄 실행되면서 해당 변수가 선언된 라인을 통과하면 되면 값이 할당된다!

❗️변수 호이스팅 (var, let, const 키워드)

  • 자바스크립트의 모든 선언에는 호이스팅이 일어난다.
  • let, const, class를 이용한 선언문을 호이스팅이 발생하지 않는 것처럼 동작한다.
  • var 키워드로 선언된 변수와는 달리 let 키워드로 선언된 변수를 선언문 이전에 참조하면 참조 에러(ReferenceError)가 발생한다.
  • 이는 let 키워드로 선언된 변수는 스코프의 시작에서 변수의 선언까지
    일시적 사각지대(Temporal Dead Zone; TDZ)에 빠지기 때문이다.

변수 생성과 호이스팅

변수는 3단계에 걸쳐 생성된다.

1단계: 선언 단계(Declaration phase)

  • 변수를 실행 컨텍스트의 변수 객체에 등록한다.
  • 이 변수 객체는 스코프가 참조하는 대상이 된다.

2단계: 초기화 단계(Initialization phase)

  • 변수 객체에 등록된 변수를 위한 공간을 메모리에 확보한다.
  • 이 단계에서 변수는 undefined로 초기화 된다.

3단계: 할당 단계(Assignment phase)

  • undefined로 초기화된 변수에 실제 값을 할당한다.

var 키워드로 선언한 변수는 선언 단계와 초기화 단계가 한번에 이뤄진다. 즉, 스코프에 변수를 등록(선언 단계)하고 메모리에 변수를 위한 공간을 확보한 후, undefined로 초기화한다. 따라서 변수 선언문 이전에 변수에 접근하여도 스코프에 변수가 존재하기 때문에 에러가 발생하지 않는다. 다만 undefined를 반환한다. 이후 변수 할당문에 도달하면 비로소 값이 할당된다.

let 키워드로 선언된 변수는 선언 단계와 초기화 단계가 분리되어 진행된다. 즉, 스코프에 변수를 등록(선언 단계)하지만 초기화 단계는 변수 선언문에 도달했을 때(코드 실행 후) 이뤄진다. 초기화 이전에 변수에 접근하려고 하면 참조 에러가 발생한다. 이는 아직 변수가 초기화되지 않았기 때문이다. 즉, 변수를 위한 메모리 공간이 아직 확보되지 않았기 때문이다. 따라서 스코프의 시작 지점부터 초기화 시작 지점까지는 변수를 참조할 수 없다. 스코프의 시작 지점부터 초기화 시작 지점까지의 구간을 ‘일시적 사각지대(Temporal Dead Zone; TDZ)’라고 부른다.

문제가 생기는 경우

a 파일은 b 파일을 import
b 파일은 c 파일을 import
c 파일은 a 파일을 import

순환 참조는 Hoisting 때문에 발생할 수 있다.
-> 구조를 잘 잡아야 한다

요약

  • 함수와 변수는 코드를 실행하기 전에 실행 컨텍스트를 위해 메모리에 저장됩니다. 이것을 호이스팅 이라고 한다.
  • 함수는 전체 함수에 대한 참조와 함께 저장되고, var 키워드가 있는 변수는 undefined, let 및 const 키워드가 있는 변수 는 초기화되지 않은 상태로 메모리에 저장됩니다.

결론

호이스팅 메카니즘을 적절히 이해하는 것은 호이스팅에 의해 발생하는 잠재적 버그와 혼란을 피하도록 도와준다.

undefined나 reference error와 같이 호이스팅의 사이드 이펙트(Side Effect)를 피하기 위해서는 항상 변수를 현재 스코프 최상단에서 선언하도록 하고, 선언과 함께 초기화를 해야한다.

면접 , 인터뷰

힙 메모리
let , const, 함수는 어디에 할당이 되냐
링크 : https://charming-kyu.tistory.com/19

https://dev.to/lydiahallie/javascript-visualized-hoisting-478h
https://velog.io/@hoo00nn/%ED%98%B8%EC%9D%B4%EC%8A%A4%ED%8C%85Hoisting-%EC%9D%B4%EB%9E%80

0개의 댓글