JavaScript의 실행 콘텍스트에서 var, function 선언문 등은, \
해당 스코프의 맨 앞으로 옮겨진 것처럼 동작한다.
호이스팅은 ES5나 그 이후 표준의 공식 언어는 아니다.
다만 사람들이 이러한 JavaScript의 특성을 이해하기 위해 차용한 단어이다.
JavaScript는 ES6에 도입된 let, const를 포함하여
모든 선언(var, let, const, function, function*, class)을 호이스팅한다.
먼저, 변수는 다음 3단계에 걸쳐 생성 된다.
변수 hoisted를 실행 컨텍스트의 변수 객체(Variable Object)에 등록한다.
이 변수 객체는 스코프가 참조하는 대상이 된다.
var hoisted
변수 객체(Variable Object)에 등록된 변수 hoisted를 위한 공간을 메모리에 확보한다.
그 공간은 아직 아무것도 할당되지 않은 상태이며, undefined로 초기화된다.
var hoisted
console.log(hoisted) // undefined
undefined로 초기화된 변수에 실제 값을 할당한다.
var hoisted = "test";
console.log(hoisted) // "test"
var
출처 링크
위 그림처럼 var 키워드로 선언된 변수는
선언 단계(스코프에 변수를 등록)와
초기화 단계(메모리에 변수를 위한 공간을 확보한 후 undefined로 초기화)가
한번에 이루어진다.
따라서 변수 선언문 이전에 변수에 접근하여도
스코프에 변수가 존재하기 때문에 에러가 발생하지 않는다.
다만 undefined를 반환한다.
이후 변수 할당문에 도달하면 비로소 값이 할당된다
let
출처 링크
일시적 사각지대(Temporal Dead Zone; TDZ)
스코프의 시작 지점부터 초기화 시작 지점까지의 구간
let 키워드로 선언된 변수는 선언 단계(스코프에 변수를 등록)와 초기화 단계(메모리에 변수를 위한 공간을 확보한 후 undefined로 초기화)가 분리되어 진행된다. 따라서 그림과 같이 초기화 이전에 변수에 접근하려고 하면 변수를 위한 메모리 공간이 아직 확보되지 않은 상태이기 때문에 참조 에러(ReferenceError)가 발생한다.
결국 ES6에서는 호이스팅이 발생하지 않는 것 같아 보이지만 그렇지 않다.
let name = '해리포터'; // 전역 변수
{
console.log(name); // ReferenceError: name is not defined
let name = '론위즐리'; // 블록 안의 지역 변수
}
let 키워드로 선언한 지역 변수 name이 블록 레벨 스코프 내에서 호이스팅 됐지만, 아직 초기화나 할당 단계에 진입하지 않고 일시적 사각지대(TDZ)에 있다. 그러므로 name의 값이 출력되지 않고 참조 에러(ReferenceError)가 발생한다.
name(); // 해리포터
function name(){
console.log('해리포터');
}
JavaScript에서는 코드에서 함수를 선언하기 전에 함수를 사용할 수 있다.
name(); // TypeError name is not a function
var name = function(){
console.log('해리포터');
}
하지만 이는 함수 선언식으로 선언할 경우에 한정한다. 위와같이 함수 표현식으로 선언할 경우 호이스팅에 영향을 받지 않는다.
var name = '해리포터';
function name(str) {
return ('안녕' + str);
}
console.log(typeof name); // Output: string
선언의 위치를 반대로해도 여전히 name을 함수로 간주한다.
Hoisting
JavaScript Hoisting
let, const | PoiemaWeb
🔥🕺🏼 시작적인 자바스크립트 : 호이스팅