[JS] 호이스팅(hoisting) 똑바로 알기(Feat. TDZ)

apro_xo·2022년 3월 8일
2
post-thumbnail

1. 호이스팅이란?

1-0. 호이스팅 가볍게 짚어보기

호이스팅을 통해 선언과 할당을 분리한다.

모든 변수/함수 선언을 해당 스코프의 최상단으로 끌어올린 듯 한 현상이 일어난다.

🔥 여기서 주의할 점은
모든 변수, 함수 선언을 코드 상에서 실제로, 물리적으로 최상단으로 끌어올리는 것이 아닌 내부적으로 끌어올리는 것이다.
메모리의 변화 또한 없다.

1-1. 내부적으로 어떤 일이 발생하는가?

모든 선언이 우선적으로 실행 컨텍스트(메모리)에 저장된다

이것 때문에 선언이 끌어올려진다는 표현이 나온 것 같다.
실제로 물리적으로 올려지는 것이 아니라 내부적으로 저런 방식에 의해 코드가 끌어올려진 듯한 현상이 나타난다고 보면 될 것 같다.

그리고 곧 이것이 호이스팅(hoisting)이다.

1-2. ✨호이스팅을 제대로 정의하면?✨

호이스팅이란❓
자바스크립트 엔진이 전체 코드를 먼저 스캔한 후, 변수 선언 정보를
실행 컨텍스트에 기록해놓는데, 이러한 작업 때문에 선언문이 유효한 스코프 내에서 최상단으로 끌어 올려지는 듯한 현상을 말한다.

2. 호이스팅에 대해 잘못 알고있던 사실✔

🔥 호이스팅은 var 선언만 일어난다? Nope❌

흔히 호이스팅에 대한 자료나 인터넷 검색을 해보면
"var을 이용한 변수 선언은 호이스팅이 일어나지만, const,let을 이용한 변수 선언은 호이스팅이 일어나지 않는다" 라는 정보가 많이 나온다.
필자도 이렇게 알고있었다...🙄 저것은 잘못된 표현이다.

var, const, let 상관없이 모든 선언에서 호이스팅이 이루어진다.

1-1 에서 내부적으로 모든 선언이 우선적으로 메모리에 저장된다고 하였는데, 여기에 집중해야한다.

호이스팅은 모든 변수/함수 선언을 내부적으로 최상단으로 끌어올리는 것이고, 내부적으로는 모든 선언이 우선적으로 메모리에 저장된다는 것이다.

이 말은 var, const, let 상관없이 모든 선언에서 호이스팅이 일어난다는 것을 얘기하는 것이다.

🔥 그렇다면 왜 const, let은 호이스팅이 일어나지 않는 것 처럼 보였을까?

예시 코드를 확인해보자.

console.log(myname);
console.log(myname2);
var myname = 'hong';
let myname2 = 'kwon';

위 코드를 돌려보면 결과는 아래와 같다.

myname을 찍어보면 에러가 나지 않고 undefined가 출력이 되고, myname2를 찍어보면 레퍼런스 에러가 난다.

이 결과를 보면 마치 var 선언은 호이스팅이 일어났기 때문에 에러가 나지않고 const, let 선언은 호이스팅이 일어나지 않기 때문에 에러가 발생한다고 생각할 수도 있다. ❌하지만 아니다.❌

var과 const, let 간에 결정적인 차이 때문에 이러한 현상이 발생한다.
차이를 알아보자.

3. var과 const, let 의 차이

  • var은 호이스팅 후 undefined로 초기화가 되어 메모리에 저장된다.
  • const, let은 호이스팅 후 어떠한 값으로도 초기화 되지 않으며 선언만 되어 저장된다.

3-1. let은 왜 레퍼런스 에러가 나는가?

위의 코드를 돌려보면 let으로 선언한 변수는 레퍼런스 에러가 났다.

변수가 초기화 되지 않으면 변수를 참조할 수 없다

3-2. 종합

const, let은 호이스팅이 일어난 후 어떠한 값으로도 초기화가 되지 않으며, 초기화되지 않은 변수는 참조할 수 없기 때문에 console.log( ) 코드를 실행하지 못하고 레퍼런스 에러가 나는 것이다.

이러한 현상 때문에 const, let은 호이스팅이 되지 않는다는 오해를 불러왔던 것이다.

4. 함수의 호이스팅

함수에서도 호이스팅이 일어난다.
다시 한 번 상기시켜 보면,

내부에서 변수/함수의 선언을 우선적으로 메모리에 저장하는 것이 호이스팅이다.

4-1. 함수 표현법

함수를 나타내는 방법은 크게 두 가지가 있다.

  1. 함수 선언문

  2. 함수 표현식

4-1-1. 함수 선언문

function tempFunc(text) {
  console.log(text);
}

4-1-2. 함수 표현식

var tempFunc = (text)=> {
  console.log(text);
}

var tempFunc = function(text) {
  console.log(text);
}
  • 함수 선언문으로 나타낸 함수는 호이스팅이 일어난다.
  • 함수 표현식으로 나타낸 함수는 호이스팅이 일어나지 않는다.

5. 변수/함수 호이스팅 예시 코드

코드

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}`);
  
}

varlet의 호이스팅 후 초기화 상태와 함수 선언문함수 표현식의 호이스팅 차이에 집중해서 참고하면 될 것 같다.

6. TDZ ( Temporal Dead Zone )

일시적 사각지대❓
👉 let 또는 const로 변수를 선언했을 때, 선언 이전에 식별자를 참조할 수 없는 구역
👉 호이스팅으로 변수의 선언이 이루어졌지만 변수의 초기화가 이루어지지 않은 지점
👉 변수를 참조할 수 없는 지점

profile
유능한 프론트엔드 개발자가 되고픈 사람😀

0개의 댓글