코드가 실행되기 전에 변수나 함수 선언이
해당 스코프 최상단으로 끌어 올려진 것 같은 현상을 말함.
자바스크립트 엔진은 코드를 실행하기 전에
실행 가능한 코드를 형상화하고 구분하는 과정(실행 컨텍스트를 위한 과정)을 거친다.
자바스크립트 엔진은 코드를 실행하기 전에
실행 컨텍스트를 위한 과정에서 모든 선언(var, let, const, function, class)를 스코프에 등록한다.
코드 실행 전 이미 변수나 함수 선언이 저장되어 있기에
선언문보다 참조, 호출이 먼저 나와도 오류 없이 동작한다.
실행 컨텍스트는 실행 가능한 코드가 실행되기 위해 필요한 환경을 의미,
실행되기 전 이러한 실행 컨텍스트 과정(코드들을 구분하는 과정)을 거친다.
자바스크립트 실행 컨텍스트에 대한 이해가 호이스팅을 이해하는 데 도움이 된다고 한다.
호이스팅 = 자바스크립트 실행 컨텍스트에 의해서 위에 설명한 현상이 일어나는 것.
즉, 선언이 코드 실행보다 먼저 메모리에 저장되는 과정으로 인한 현상을 말함
호이스팅이라는 용어는 선언이 끌어올려져 '먼저 메모리에 저장되었다'라는 것을 의미한다.
그렇기 때문에 모든 선언은 호이스팅이 일어난다는 말이 참이 되는 것.
그 말인즉슨 선언문 이전에 참조해서 에러를 발생시킨다고 해서 호이스팅이 일어나지 않았다는 건 아니다.
var는 선언과 함께 undefined로 초기화돼 메모리에 저장된다고 한다.
하지만 let과 const는 초기화되지 않은 상태로 선언만 메모리에 저장되기 때문에 오류가 발생한다.
초기화가 되지 않으면 변수를 참조할 수 없으며 그렇기에 참조 에러가 일어나는 것.
let foo = 1;
{
console.log(foo);
let foo = 2;
}
var 키워드로 선언한 변수는 선언 단계와 초기화 단계가 한번에 이뤄진다.
즉, 스코프에 변수를 등록(선언 단계)하고 메모리에 변수를 위한 공간을 확보한 후, undefined로 초기화한다.
따라서 변수 선언문 이전에 변수에 접근하여도 스코프에 변수가 존재하기 때문에 에러가 발생하지 않는다.
다만 undefined를 반환한다. 이후 변수 할당문에 도달하면 비로소 값이 할당된다.
let으로 선언된 변수는 선언 단계와 초기화 단계가 분리되어 진행된다.
스코프에 변수를 등록(선언 단계)하지만 초기화 단계는 변수 선언문에 도달했을 때(코드 실행 후) 이뤄진다.
초기화 이전에 변수에 접근하려고 하면 참조 에러가 발생한다.
이는 아직 변수가 초기화되지 않았기 때문이다.
즉, 변수를 위한 메모리 공간이 아직 확보되지 않은 상태이기에
스코프의 시작 지점부터 초기화 시작 지점까지는 변수를 참조할 수 없다.
이 구간을 **‘일시적 사각지대(Temporal Dead Zone; TDZ)’라고 부른다.
console.log(text); // 선언 + 초기화 상태
text = 'Jinyoung'; // 선언 + 초기화 + 할당 상태
var text;
console.log;
// 호이스팅 때문에 선언이 끌어올려져서 오류가 안남
console.log(text); 선언된 상태, 초기화(메모리 공간 확보, undefined로 초기화)가 되지 않아 참조 불가능 -> 에러
let text; // 여기서 초기화 단계가 실행
// 호이스팅 때문에 선언이 끌어올렸으나 초기화가 되지 않은 상태에서 참조해 오류 발생
const text;
//에러 발생, const 키워드는 재할당이 불가능하다.
그렇기 때문에 선언과 동시에 할당해야 한다
foo1(); // 함수 선언문에서는 호이스팅 발생 O
foo2(); // 함수 표현식이라 호이스팅 발생 X
function foo1 () {
console.log('hello');
}
var foo2 = function() {
console.log('hello');
}
출처 : 하나몬 블로그 (https://hanamon.kr/javascript-%ED%98%B8%EC%9D%B4%EC%8A%A4%ED%8C%85%EC%9D%B4%EB%9E%80-hoisting/)
내가 이해하기 쉽게 조금의 수정만 들어갔다.