우리는 호이스팅을 흔히 함수의 선언과 변수의 선언을 파일의 맨 위로 끌어올리는 것으로 알고있다.
하지만 MDN의 설명에 따르면 자바스크립트에서 호이스팅은 인터프리터가 변수와 함수의 메모리 공간을 선언 전에 미리 할당하는 것을 의미하며, var로 선언한 변수의 경우 호이스팅시 undefined로 변수를 초기화한다.
let과 const는 호이스팅 시 변수를 초기화 하지않는다.
console.log(dog); // undefined
console.log(cat1); // Cannot access 'cat1' before initialization
console.log(cat2); // Cannot access 'cat2' before initialization
var dog = "멍멍";
const cat1 = "야옹";
let cat2 = "야오옹";
위의 코드를 보면 var는 undefined 가 출력되고 let,const는 오류가 난 것을 볼 수 있다. 왜 이런 결과가 나온 것일까? 이러한 결과는 자바스크립트의 변수 생성 단계와 관련이 있다.
이미지 출처
let 과 const는 위의 이미지에서 볼 수 있듯이 3단계를 거친다.
Declaration phase(선언 단계)
변수가 실행 컨텍스트의 변수 객체에 등록된다.
변수 객체는 스코프가 참고하는 대상이 된다.
Initialization phase(초기화 단계)
선언 단계에서 등록되었던 변수를 위한 메모리를 만드는 단계이다.
이 단계에서 할당된 메모리에 undefined를 할당한다.
Assignment phase(할당 단계)
초기화 단계에서 undefined로 초기화된 메모리에 다른 값을 할당한다.
반면에 var는 let,const와 다르다.
이미지 출처
var는 Declaration phase(선언 단계)와 Initialization phase(초기화 단계)가 동시에 진행된다.
그래서 let 과 const는 실행 컨텍스트의 변수 객체에 변수가 등록은 되었지만 메모리에는 할당되지 않아서 접근할 수 없어 오류가 뜨지만 var는 선언 단계와 초기화 단계가 동시에 이루어지기 때문에 오류가 발생하지않고 undefined가 출력된다.
cat(); // "야옹"
dog(); // "dog is not a function"
function cat() {
console.log("야옹");
}
var dog = function () {
console.log("멍멍");
};
이미지 출처
함수 선언식은 위의 이미지에서 볼 수 있듯이 3가지 단계가 전부 동시에 일어나기 때문에 함수 호출을 먼저해도 함수 내용이 출력된다.
하지만 함수 표현식은 var dog; 가 호이스팅이 적용되어 위로 올라갔고 dog에 할당될 함수 로직은 호출이 된 이후에 선언되었으므로 dog는 함수로 인식되지 않고 변수로 인식된다.
사이트 참고 :
https://nuhends.tistory.com/111
https://developer.mozilla.org/ko/docs/Glossary/Hoisting
https://joshua1988.github.io/web-development/javascript/function-expressions-vs-declarations/#%ED%95%A8%EC%88%98-%EC%84%A0%EC%96%B8%EC%8B%9D---function-declarations