호이스팅을 통해 선언과 할당을 분리한다.
모든 변수/함수 선언을 해당 스코프의 최상단으로 끌어올린 듯 한 현상이 일어난다.
🔥 여기서 주의할 점은
모든 변수, 함수 선언을 코드 상에서 실제로, 물리적으로 최상단으로 끌어올리는 것이 아닌 내부적으로 끌어올리는 것이다.
메모리의 변화 또한 없다.
모든 선언이 우선적으로 실행 컨텍스트(메모리)에 저장된다
이것 때문에 선언이 끌어올려진다는 표현이 나온 것 같다.
실제로 물리적으로 올려지는 것이 아니라 내부적으로 저런 방식에 의해 코드가 끌어올려진 듯한 현상이 나타난다고 보면 될 것 같다.
그리고 곧 이것이 호이스팅(hoisting)이다.
호이스팅이란❓
자바스크립트 엔진이 전체 코드를 먼저 스캔한 후, 변수 선언 정보를
실행 컨텍스트에 기록해놓는데, 이러한 작업 때문에 선언문이 유효한 스코프 내에서 최상단으로 끌어 올려지는 듯한 현상을 말한다.
흔히 호이스팅에 대한 자료나 인터넷 검색을 해보면
"var
을 이용한 변수 선언은 호이스팅이 일어나지만, const
,let
을 이용한 변수 선언은 호이스팅이 일어나지 않는다" 라는 정보가 많이 나온다.
필자도 이렇게 알고있었다...🙄 저것은 잘못된 표현이다.
var, const, let 상관없이 모든 선언에서 호이스팅이 이루어진다.
1-1
에서 내부적으로 모든 선언이 우선적으로 메모리에 저장된다고 하였는데, 여기에 집중해야한다.
호이스팅은 모든 변수/함수 선언을 내부적으로 최상단으로 끌어올리는 것이고, 내부적으로는 모든 선언이 우선적으로 메모리에 저장된다는 것이다.
이 말은 var, const, let 상관없이 모든 선언에서 호이스팅이 일어난다는 것을 얘기하는 것이다.
예시 코드를 확인해보자.
console.log(myname);
console.log(myname2);
var myname = 'hong';
let myname2 = 'kwon';
위 코드를 돌려보면 결과는 아래와 같다.
myname을 찍어보면 에러가 나지 않고 undefined가 출력이 되고, myname2를 찍어보면 레퍼런스 에러가 난다.
이 결과를 보면 마치 var 선언은 호이스팅이 일어났기 때문에 에러가 나지않고 const, let 선언은 호이스팅이 일어나지 않기 때문에 에러가 발생한다고 생각할 수도 있다. ❌하지만 아니다.❌
var과 const, let 간에 결정적인 차이 때문에 이러한 현상이 발생한다.
차이를 알아보자.
- var은 호이스팅 후
undefined
로 초기화가 되어 메모리에 저장된다.- const, let은 호이스팅 후 어떠한 값으로도 초기화 되지 않으며 선언만 되어 저장된다.
위의 코드를 돌려보면 let으로 선언한 변수는 레퍼런스 에러가 났다.
변수가 초기화 되지 않으면 변수를 참조할 수 없다
const, let은 호이스팅이 일어난 후 어떠한 값으로도 초기화가 되지 않으며, 초기화되지 않은 변수는 참조할 수 없기 때문에 console.log( ) 코드를 실행하지 못하고 레퍼런스 에러가 나는 것이다.
이러한 현상 때문에 const, let은 호이스팅이 되지 않는다는 오해를 불러왔던 것이다.
함수에서도 호이스팅이 일어난다.
다시 한 번 상기시켜 보면,
내부에서 변수/함수의 선언을 우선적으로 메모리에 저장하는 것이 호이스팅이다.
함수를 나타내는 방법은 크게 두 가지가 있다.
함수 선언문
함수 표현식
function tempFunc(text) {
console.log(text);
}
var tempFunc = (text)=> {
console.log(text);
}
var tempFunc = function(text) {
console.log(text);
}
- 함수 선언문으로 나타낸 함수는 호이스팅이 일어난다.
- 함수 표현식으로 나타낸 함수는 호이스팅이 일어나지 않는다.
function tempFunc() {
var value = function(){
return 'temp value';
}
var result = value();
printApple();
let banana = 'banana';
function printApple() {
console.log('apple');
}
console.log(`temp value : ${result}`);
}
function tempFunc() {
var value = undefined;
var result = undefined;
let banana;
function printApple() {
console.log('apple');
}
value = function(){
return 'temp value';
}
result = value();
printApple();
banana = 'banana';
console.log(`temp value : ${result}`);
}
var
과 let
의 호이스팅 후 초기화 상태와 함수 선언문
과 함수 표현식
의 호이스팅 차이에 집중해서 참고하면 될 것 같다.
일시적 사각지대❓
👉 let 또는 const로 변수를 선언했을 때, 선언 이전에 식별자를 참조할 수 없는 구역
👉 호이스팅으로 변수의 선언이 이루어졌지만 변수의 초기화가 이루어지지 않은 지점
👉 변수를 참조할 수 없는 지점