어디에 선언이 되어 있나 상관없이 최상단 위로 끌어 올려주는 것이다 ?? (Hoist:끌어 올리다))
변수, 함수의 선언부가 위치한 인접 스코프의 시작 지점에서 해당 식별자의 관측이 가능한 현상
JavaScript에서 호이스팅(hoisting)이란, 인터프리터가 변수와 함수의 메모리 공간을 선언 전에 미리 할당하는 것을 의미합니다.
var로 선언한 변수의 경우 호이스팅 시 undefined로 변수를 초기화합니다. 반면 let과 const로 선언한 변수의 경우 호이스팅 시 변수를 초기화하지 않습니다.
호이스팅을 설명할 땐 주로 "변수의 선언과 초기화를 분리한 후, 선언만 코드의 최상단으로 옮기는" 것으로 말하곤 합니다.
따라서 변수를 정의하는 코드보다 사용하는 코드가 앞서 등장할 수 있습니다.
다만 선언과 초기화를 함께 수행하는 경우, 선언 코드까지 실행해야 변수가 초기화된 상태가 됨을 주의하세요.
호이스팅은 (let과 const를 포함한) ECMAScript® 2015 언어 명세 이전의 표준 명세에는 나타나지 않았습니다.
호이스팅은 크게 함수 호이스팅과 변수 호이스팅으로 나뉜다.
이 3가지 규칙을 숙지하고 가보자.
MDN : JavaScript는 함수의 코드를 실행하기 전에 함수 선언에 대한 메모리부터 할당합니다. 덕분에 함수를 호출하는 코드를 함수 선언보다 앞서 배치할 수 있다.
calculateAge(1999); // 함수 선언 전에 함수를 호출 -> hoisting 이 되어 잘 작동한다.
function calculateAge(year) {
// 함수 선언.
console.log(2020 - year);
}
함수의 선언문은 식별자가 변수 객체에 수집될 때 부가적으로 해당 함수 참조에 대한 초기화까지 자동으로 이루어진다. 그래서 선언된 함수는 상단에서 참조, 호출이 가능하다.
//retirement(1990); // 작동하지 않는다
var retirement = function (year) {
// 함수의 선언 방식이 아니기 떄문에 hoisting 되지 않는다. (only work on function declaration)
console.log(65 - (2020 - year));
};
함수 표현식은 결국 어떠한 변수로 함수를 할당하는 모양새여서 이것 또한 변수 호이스팅 사례로 볼 수 있다.
var 변수이기에, 엔진은 호이스팅 동안 undefined 값을 할당할 것이다.
🔥함수 선언식은 호이스팅에 영향을 받지만, 함수 표현식은 호이스팅에 영향을 받지 않는다.
변수는 3가지 단계를 거쳐 생성
선언 : 파싱 과정에서 변수 객체가 변수에 대한 식별자들을 수집한다.
초기화 : 식별자에 메모리를 할당하고 undefined 상태를 부여한다.
할당 : 변수 안에 직접 값을 넘겨 준다.
var 는 호이스팅이 발생하면, 선언과 초기화가 거의 동시에 이루어진다.
실행 시점의 스코프 최상단에서 해당 변수에 대한 메모리가 살아있기 때문에 선언부 위치에 상관 없이 참조, 할당이 가능하다.
let과 const로 선언한 변수도 호이스팅 대상이지만, var
와 달리 호이스팅 시 undefined
로 변수를 초기화하지는 않는다.
따라서 변수의 초기화를 수행하기 전에 읽는 코드가 먼저 나타나면 예외(참조 에러)가 발생한다
호이스팅이 발생하면, 선언만 이루어지고 실행 시점에서 실질적인 선언부를 만날 때까지 초기화는 이루어지지 않는다.
이 간극만큼 해당 변수에 대한 메모리는 존재하지 않기 때문에(TDZ) 선언부 상단에서 참조, 할당이 불가능하다.
💡 var 키워드로 선언된 변수는 선언 단계와 초기화 단계가 한번에 이루어진다.
➡️ 초기화 단계에서 undefined로 초기화되기 때문에 변수 선언문 이전에 변수에 접근해도 에러가 발생하지 않고 undefined를 반환하는 것
💡 반면 let, const 키워드로 선언된 변수는 선언 단계와 초기화 단계가 분리되어 이루어진다.
➡️ 따라서, 스코프에 변수를 등록(선언단계)하지만 초기화 단계는 변수 선언문에 도달했을 때 이루어지므로 초기화 이전에 변수에 접근하면 참조 에러(ReferenceError)가 발생하는 것
let,const 로 선언한 변수는 스코프의 시작 지점부터 초기화 단계 시작 지점(변수 선언문)까지 변수를 참조할 수 없다.
let, const 가 동작하는 과정에서 스코프의 진입지점과 해당 식별자의 실질적 선언부 사이를 일시적 사각지대, TDZ(Temporal Dead Zone)
라고 한다.
여기서 변수는 존재하지만, 초기화가 되어있지 않다.
MDN
호이스팅 영문 자료
호이스팅 블로그 - 영문자료해석
Github - prepare_frontend_interview