Wecode TIL - Hoisting

Hoisting

hoisting이란 함수나 안에 있는 선언이나 변수를 모두 끌어올려서 해당 함수 유효 범위의 최상단에 선언하는 것을 말한다.(선언과 할당의 분리라고 생각하는것이 쉽다)
let, const를 포함하여 모든 선언(var, let, const, function, function*, class)을 호이스팅한다.
하지만 var 키워드로 선언된 변수와는 달리 let 키워드로 선언된 변수를 선언문 이전에 참조하면 참조 에러(ReferenceError)가 발생한다. 이는 let 키워드로 선언된 변수는 스코프의 시작에서 변수의 선언까지 일시적 사각지대(Temporal Dead Zone; TDZ)에 빠지기 때문이다.

변수의 생성 단계

  1. 선언단계
    변수를 실행 컨텍스트의 변수 객체에 등록한다.
  2. 초기화 단계
    변수 객체에 등록된 변수를 위한 공간을 메모리에 확보. 이 단계에서 변수는 undefined로 초기화
  3. 할당단계
    undefined로 초기화된 변수에 실제 값을 할당

여기서 var는 선언 단계와 초기화 단계가 한번에 이루어진다. 즉 스코프에 변수를 등록하고 메모리 확보한 후, undefined로 초기화. 따라서 변수 선언문 이전에 변수에 접근하여도 스코프에 변수가 존재하여, 에러가 발생x

반대로 let은 선언과 초기화 단계가 분리되어 있다. 그렇기 때문에 초기화가 되지 않은 시점에서 변수를 참조할 수 없기때문에 오류가 발생한다. 초기화 시작 시점까지 구간을 일시적 사각지대라고한다.(Temporal Dead Zone)

  1. 변수 호이스팅

보통 선언이 되지 않은 변수를 참조할 때는 이런 오류가 발생한다.

하지만 이 예제를 보면 오류가 발생하지 않고, a가 정의되어 있지 않는다고 한다. 이 이유가 바로 Hoisting때문이다.

자바스크립트의 경우 엔진에서 아래와 같이 해석을 하기 때문이다.
이러한 호이스팅의 문제는 error가 발생하지 않는 데 있다.
이걸 해결하기 위해서는 var를 사용하지말고 ,let이나 const를 사용하자.

대부분의 프로그래밍 언어는 블록 레벨 스코프(Block-level scope)를 따르지만 자바스크립트는 함수 레벨 스코프(Function-level scope)를 따른다.

함수 레벨 스코프(Function-level scope) (var)
함수 내에서 선언된 변수는 함수 내에서만 유효하며 함수 외부에서는 참조할 수 없다. 즉, 함수 내부에서 선언한 변수는 지역 변수이며 함수 외부에서 선언한 변수는 모두 전역 변수이다.
블록 레벨 스코프(Block-level scope) (let, const)
모든 코드 블록(함수, if 문, for 문, while 문, try/catch 문 등) 내에서 선언된 변수는 코드 블록 내에서만 유효하며 코드 블록 외부에서는 참조할 수 없다. 즉, 코드 블록 내부에서 선언한 변수는 지역 변수이다.

  1. 함수 호이스팅
    함수는 함수선언문만 호이스팅이된다.
    변수의 선언이 초기화나 할당시에 발생하는것이 아니라, 최상위로 호이스트 된다는 것을 명심해야된다. 다음 코드를 보자.
function showName() {
     console.log("First Name : " + name);
     var name = "Ford";
     console.log("Last Name : " + name);
}
showName();

First Name : undefined
Last Name : Ford
First Name이 undefined인 이유는 지역변수 name이 호이스트 되었기 때문이다.
이 코드는 자바스크립트 엔진에 의해 다음과 같이 해석된다.

function showName() {
     var name; // name 변수는 호이스트 되었습니다. 할당은 이후에 발생하기 때문에, 이 시점에 name의 값은 undefined 입니다.
     console.log("First name : " + name); // First Name : undefined
     name = "Ford"; // name에 값이 할당 되었습니다.
     console.log("Last Name : " + name); // Last Name : Ford
}

호이스트 되었을때, 함수 선언은 변수선언을 덮어 쓴다.

좋은 웹페이지 즐겨찾기