본문 바로가기

Language/Javascript

[Javascript] Hoisting이란?

호이스팅이란?

코드 실행 전, 변수/함수선언이 파일의 맨 위로 끌어 올려진 "것 같은 현상"을 이야기한다.

 

Hoisting이 발생하는 이유

자바스크립트 엔진 동작의 특징 때문!

  • 코드를 실행하기 전 실행 가능한 코드를 형상화하고 구분하는 과정을 거침 (실행 컨텍스트를 위한 과정)
  • 코드를 실행하기 전 실행 컨텍스트를 위한 과정에서 모든 선언들(var, let, const, function, class)을 메모리에 저장.
  • 코드 실행 전 이미 변수/함수 선언이 메모리에 저장되어 있기 때문에 선언문보다 참조/호출이 먼저 나와도 오류 없이 동작.
    (정확히는 var 키워드로 선언한 변수와 함수 선언문일 경우 오류 없이 동작.)
  • 따라서 이는 선언이 파일의 맨 위로 끌어올려진 것 처럼 보이게 한다.

*실행 컨텍스트는 실행 가능한 코드가 실행되기 위해 필요한 환경을 의미하고 실행되기전 이러한 실행 컨텍스트 과정(코드를 구분하는 과정)을 거침.

 

 

Hoisting의 특징

  • 자바스크립트의 모든 선언에는 호이스팅이 일어남.
  • let,const,class를 이용한 선언문은 호이스팅이 발생하지 않는 것 처럼 동작한다.
    (선언 전에 호출하면 ReferenceError발생)
  • 이 같은 현상이 발생하는 이유는 스코프의 시작에서 변수의 선언까지 “일시적 사각지대”에 빠지기 때문.
  • var은 선언과 함께 undefined로 초기화 되어 메모리에 저장되지만, let, const는 초기화 되지 않은 상태로 메모리에 올라가기 때문에 참조에러 발생.
let num = 9;
{//Block Scope
  console.log(num);
  let num = 2;
}

[예시] 위 예시에서 선언이 hoisting되었으므로 block scope에서 num을 찾을 수 없음.

 

변수생성과정

1단계) 선언 단계 (Declaration Phase)

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

 

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

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

 

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

  • undefined로 초기화된 변수에 실제 값을 할당.
  • var 키워드로 선언한 변수는 선언 단계와 초기화 단계가 한번에 이루어짐.
  • let키워드로 선언된 변수는 선언단계와 초기화 단계가 분리되어 실행된다. 
  • let, const의 경우 초기화는 코드 실행 후, 변수 선언문에 도달했을 때 이루어짐.따라서 초기화 이전에 변수 접근시 변수를 위한 메모리 공간이 확보되지 않았기 때문에 에러발생.
  • 스코프의 시작 지점부터 초기화 시작 지점까지의 구간을일시적 사각지대(Temporal Dead Zone; TDZ)라고 부름.

 

Hoisting 테스트를 위한 몇가지 실습

 

1)

console.log(name);
//선언된 변수도 없고 할당된 메모리 공간도 없으므로
//ReferenceError 발생

 

console.log(name);
name = "Jook";

//위 예제와 동일하게 선언이 되지 않았으므로
//ReferenceError 발생

 

console.log(name);
name="Jook";

var name;
//var 키워드로 name을 선언하였으므로 에러발생은 안함.
//undefined 출력

console.log(name);
//Jook 출력

 

2)

console.log(name);
let name;
//name 변수 선언은 되었지만 초기화 되지 않음.
//ReferenceError 발생.

 

let name;
console.log(name);
//name 변수 선언
//선언부에서 name을 undefined 초기화.
//undefined 출력.

 

3)

//Func1은 함수 선언문으로 Hoisting되어 정상 실행
console.log(Func1);//[Function: Func1] 

//Func2은 함수 표현식으로 변수 선언,초기화까지만 진행된 상태.
console.log(Func2);//undefind

Func1();//Func1 출력
Func2();//Func2 is not a function 출력.

function Func1(){
	console.log("Func1");
}

var Func2 = function(){
	console.log("Func2");
}

 

 

[참고 https://hanamon.kr/javascript-%ED%98%B8%EC%9D%B4%EC%8A%A4%ED%8C%85%EC%9D%B4%EB%9E%80-hoisting/]