EtoC

Hoisting(호이스팅) 본문

Language/JavaScript

Hoisting(호이스팅)

게리드 2023. 7. 31. 13:40

1. 호이스팅이란?

호이스팅이란 인터프리터가 모든(함수,변수)선언문의 메모리공간을 선언전에 미리 할당하여 상단으로 올려서 선언문을 유효범위의 최상단으로 옮겨진것처럼 작동하는 자바스크립트의 독특한 특징을 말한다.

유효범위?
변수에 접근할 수 있는 범위

block-level-scope?

{}로 쌓여진 범위, let,const로 변수생성시 유효한 범위.

function-level-scope?

function(){}의 {}내의 범위, var로 변수생성이 유효한 범위.

유효범위의 최상단?
변수가 함수안에 정의: 선언문이 함수의 최상단으로 호이스팅 된다.
변수가 함수밖에 정의: 선언문이 전역의 최상단으로 호이스팅 된다.

아래의 코드를 보면는 인터프리터에의해 위에서부터 한줄씩 실행되기때문에 reference error가 나야한다.

console.log(a);

var a = 1;

하지만 undefined가 출력된다.

 

이는 자바스크립트의 엔진은 모든 선언문을 소스코드에서 찾아내 먼저 실행하여 평가한 뒤, 선언문을 제외하고 소스코드를 위에서부터 실행하기 때문이다.

위처럼 변수선언이 위에서부터 코드가 실행되는 시점(런타임)이아닌 그 이전에 실행되기때문에 변수 또는 함수 선언문이 코드의 상단에 선언된것처럼 동작하는것을 호이스팅이라 한다.

2. 변수선언과 값의 할당

1. 변수의 선언

자바스크립트 엔진은 변수선언을 선언과 초기화라는 2단계로 수행한다.

var name; //변수 선언

console.log(name); //undefined
  • 선언 : 변수명을 등록하여 자바스크립트 엔진이 변수의 존재를 인지하게 하는것.
  • 초기화 : 값을 저장 할 메모리공간을 확보하고 undefined를 할당하여 초기화하는것.

한마디로 변수선언변수를 초기화하는 구문이다.

2. 값의 할당

말그대로 변수에 값을 할당(저장)하는 것이다. 값을 할당할 때는 할당연산자=을 사용한다.

name = "javaScript"; //값의 할당

값의 할당은 변수선언과 함께 한문장으로 단축표현 할 수 있다.

var name = "javaScript";

제대로 공부하지않고 이렇게 쓰는것만 알고있어서 선언과 할당이 서로 다른 시점에서 실행되는것을 몰랐다.

자바스크립트 엔진은 이렇게 단축표현을해도 선언과 할당을 2개의 문으로 나누어 따로 실행한다.
변수선언런타임 전에 먼저 실행되고, 값의 할당은 코드가 순차적으로 실행되는 런타임에 실행된다.

좀더 쉽게 말하자면 변수선언은 자바스크립트 엔진 구동시 최상단으로 호이스팅이 되고, 값의 할당은 런타임때 실행되기때문에 코드가쓰여지 위치에서 할당된다.(호이스팅 안됨)


3. 호이스팅의 종류

호이스팅은 키워드를 사용한 변수선언문이나 함수선언문에서만 발생되기때문에 아래처럼 단순하게 선언만 한경우는 참조에러가 난다.

식별자 호이스팅

변수 선언문var,let,const, function, function*, class 키워드를 사용하여 선언되는 모든 식별자는 호이스팅이 일어난다.

🔍 변수에 대하여

1. var 키워드

  • var는 변수 선언과 undefined로 초기화가 동시에 진행된다.
  • undefined는 자바스크립트의 원시타입의 하나로 '값'으로 인식되기때문에 에러가 발행하지 않는다.
  • var로 선언된 변수는 오직 function-level-scope(함수의 코드블록)만을 지역 스코프로 인지한다.
  • 함수외부에서 var로 선언한 변수는 코드블록 내에서 선언해도 모두 전역변수가 되어 코드의 최상단에서 호이스팅 된다.

이로인해 var는 의도치않게 변수가 중복되는 경우가 생기는데 이를 방지하기위해 let과 const가 등장하였다.

2. let / const 키워드

  • 위 사진을보면 let과 const는 호이스팅이 일어나지 않은것처럼 동작하지만 실제로는 호이스팅이 일어났다.
  • let은 var과 달리 초기화단계만 이루어지지 않았을뿐 자바스크립트엔진은 이미 선언을 실행해두었고 변수 선언문에 도달했을때 초기화가 일어난다.
  • const는 변수의 선언과 초기화,할당이 모두 동시에 일어나야한다.
  • 때문에 초기화가 진행되기 전에 변수에 접근하려하면 refrence에러가 나는것이다.
  • 이렇게 스코프의 시작점부터 let과const가 위치한(초기화)지점까지 변수를 참조할 수 없는 구간을 TDZ(Temporal Dead Zone)라한다.

3. function(함수)

1. 함수 선언식

  • 함수명이 정의되어있고 별도의 할당이 없는 일반적인 함수 선언방식이다.
  • 선언,초기화,할당이 한번에 이루어져서 함수전체가 스코프 최상단으로 호이스팅 된다.

2. 함수 표현식

  • 자바스크립트의 유연성을 활용한 선언방식으로, 별도의 변수에 할당하여 사용한다.
  • 변수는 선언과 할당을 나누어 선언부만을 호이스팅한다.

그래서 let과 같은 결과가 뜬다.
하지만 변수를 var로 선언할 경우 TypeError가 발생한다.

var로 선언하면 초기화가 undefined 로 add가 초기화되는데 호출할때는 함수로 호출을해서 타입에러가 뜬다.

함수 선언식의경우 함수전체가 호이스팅되어 전역으로 선언될 경우, 중복된 이름이 있을수있는데, 함수 표현식을 쓰면 이를 방지할 수 있다.

4. class(클래스 선언)

  • let,const와 같이 undefined가 아닌 uninitialized로 초기화 되어 참조(referenceError)를 뱉는다.
  • 호이스팅이 되었으나 되지않았다.

4. 호이스팅 우선순위

변수선언이 함수선언보다 호이스팅의 우선순위가 높다고한다.
하지만 실제로는 우선순위가 없고 순서대로 호이스팅된다고한다.
우선순위가 존재하는 경우는 동명의 변수와 함수를 선언할 경우이고, 이 경우 변수선언이 함수선언 보다 우선순위가 높다.