thumbnail
⚡️ 호잇! 마법 같은 호이스팅
Javascript
2022.06.08

호이스팅이 뭐야? 👀

  • 호이스팅(Hoisting) 은 실제로 선언되기 전에 몇몇 타입의 변수들에 접근 가능하고 사용할 수 있는 것을 말한다.
  • 마치 변수들이 마법처럼 스코프의 최상위로 이동하는 것처럼 보인다.

마법처럼 보이기도 하는, 이 호이스팅의 내부 동작 방식을 알기위해 먼저 변수에 대해서 알아보자.


변수 (Variable)

변수의 종류

ES6 이전 단계에서 사용하던 var 와 ES6부터 생긴 let & const가 있다.

사실 varlet은 크게 다르지 않다.

대부분의 경우에는 둘을 바꾸어서 사용해도 문제가 되지 않는다.


그렇지만, 분명 다른 점이 존재한다!

  1. var 는 한 번 선언된 변수를 다시 선언할 수 있다.
var name = 'Mike'
console.log(name) // Mike

var name = 'Jane'
console.log(name) // Jane
  • 지금 name 이 두 번 선언되었는데, 전혀 문제가 되지 않는다. 같은 상황에서 let 은? 🚨 문제가 된다!

  1. var 는 선언하기 전에 사용할 수 있다.
console.log(name) // undefined

var name = 'Mike'
  • var는 이 상황에서 에러를 일으키지 않는다.
var name // 선언

console.log(name) // undefined

name = 'Mike' // 할당
  • var 로 선언한 모든 변수는 코드가 실제로 이동하지는 않지만, 최상위로 끌어올려진 것처럼 동작한다. (호이스팅)
  • console.log()에서 undefined 값을 찍는 이유 : 선언은 호이스팅 되지만, 할당은 호이스팅 되지 않기 때문이다!
  • name 이라는 변수만 호이스팅으로 인해 올려진 것이고, ‘Mike’라는 할당 값은 그 자리에 있는 것이다.
    할당은 3번째 줄에서 처리가 된다.

  1. 그렇다면 let 의 경우는?
console.log(name) // ReferenceError

let name = 'Mike'
  • 같은 상황에서 let 은 에러가 발생한다. 그렇다고 let 이 호이스팅 되지 않는 것은 아니다.
  • 사실 letconst 도 호이스팅 된다.
  • 다시 말하자면, 호이스팅은 스코프 내부 어디서든 변수 선언은 최상위에 선언된 것처럼 행동하는 것을 말한다.
    그런데 왜 var 처럼 동작하지 않고, 에러를 반환하는 것일까?

💡 이유는 TDZ(Temporal Dead Zone) 에 있다!

결론부터 말하자면, TDZ 영역에 있는 것은 사용할 수 없다.

JS는 Top-down 방식으로 코드를 동작시키는데,

먼저 선언되지 않은 변수가 호출될 경우 해당 변수가 포함된 코드를 TDZ 영역으로 인식하게 된다.

letconst 는 TDZ의 영향을 받는 변수라서, 할당하기 전에는 사용할 수 없다.


console.log(name) // Temporal Dead Zone

const name = 'Mike' // 함수 선언 및 할당

console.log(name) // 사용 가능

TDZ가 있어서 코드를 예측 가능하게 하고, 잠재적인 버그를 줄일 수 있다.

실제 선언 전에 변수에 접근하는 방식은 매우 좋지 않은 습관이며 피해야 한다.


let age = 30

function showAge() {
  console.log(age)
}

showAge()
  • 현재 이 코드는 문제가 없다.
let age = 30

function showAge() {
  console.log(age) // ReferenceError

  let age = 20 // ✘
}

showAge()
  • 여기서 let 은 호이스팅 되지 않는구나, 생각할 수도 있다.
  • 호이스팅은 스코프 단위로 일어난다.
    여기서 스코프는 함수 내부인데 let 으로 선언한 두 번째 age 변수가 호이스팅을 일으킨다.
    만약 호이스팅이 되지 않았다면, 함수 바깥의 age = 30 값이 정상적으로 찍혔어야 한다.

변수의 생성 과정

1️⃣ 선언 단계
2️⃣ 초기화 단계
3️⃣ 할당 단계

  1. var 는 선언 및 초기화 단계가 동시에 된다.
  • 초기화 단계 : undefined를 할당해주는 단계
  • 할당 전에 호출하면 에러를 내지 않고 undefined를 찍는다.
  1. let 은 선언 단계와 초기화 단계가 분리되어 진행된다.
  • 실행이 선언보다 먼저일 때, 호이스팅되면서 선언 단계가 이루어지지만 초기화 단계는 실제 코드에 도달했을 때
    실행되기 때문에 Referrence Error가 발생하게 된다.
  1. const선언+초기화+할당 동시에 된다.
let name;
name = "Mike";

var age;
age = 30;

const gender;
gender = "male";

image

  • varlet 은 선언만 해두고 나중에 할당하는 것을 허용한다. (나중에 값을 변경할 수 있기 때문에 당연하다)

  • const 에서 SyntaxError 발생하는 이유는 선언하면서 바로 할당을 안했기 때문이다.

여기서 다시 생각해보는 스코프?!

  • var : 함수 스코프 (function-scoped)

    • 함수 내에서 선언된 변수만 그 지역 변수가 되는 것이다!
  • let & const : 블록 스코프 (block-scoped)

    • 모든 코드 블록에서 선언된 변수는 코드 블록 내에서만 유효하며, 외부에서는 접근할 수 없다.
      즉, 코드 블록 내부에서 선언한 변수는 지역 변수이다.
      여기서 코드 블록은 함수, if문, for문, while문, try/catch문 등을 말한다.
function add() {
  // Block-level Scope
}

if() {
  // Block-level Scope
}

for(let i = 0; i < 10; i++;) {
  // Block-level Scope
}

🏢 함수 스코프 vs 🧱 블록 스코프

const age = 30

if (age > 19) {
  var txt = '성인'
}

console.log(txt) // '성인'
  • if문 안에서 var 로 선언한 변수는 if문 바깥에서도 사용이 가능하다. : 함수 스코프
  • letconst 는 중괄호 내부(블록 단위)에서만 사용 가능하다. : 블록 스코프
function add(num1, num2) {
  var result = num1 + num2
}

add(2, 3)

console.log(result)

image

  • var 도 함수 내에서 선언되면 함수 바깥에서는 사용할 수 없다!
    유일하게 벗어날 수 없는 스코프가 함수라고 생각하면 된다.

예측 가능한 결과를 내고, 버그를 줄이기 위해서 var 는 사용하지 않고 letconst 를 사용한다.

✨ 정리

호이스팅을 공부하면서, 변수 varlet의 차이점에 대해서 확실히 알 수 있어서 좋았다.
자바스크립트 ES6 이후로만 계속 사용해왔어서 var를 사용해본 적이 없어서 let과의 차이에 대해서
뚜렷하게 알지 못했는데 이번 기회에 확실히 잡을 수 있었다! 🤓

참고 내용

유튜브 강의 by 코딩앙마

Thank You for Visiting My Blog, Have a Good Day 😊
©2021 Developer minkyung choi, Powered By Gatsby.