자바스크립트의 호이스팅

홍태극·2023년 8월 7일
0

자바스크립트

목록 보기
2/3

자바스크립트 호이스팅? 변수가 막 위로 올라간다고요? 🚀

자바스크립트 공부하다 보면 '호이스팅(Hoisting)'이라는 말을 꼭 듣게 되죠? 뭔가 '끌어올린다'는 뜻 같은데, 이게 대체 뭘까요? 🤔

간단히 말하면, 자바스크립트 엔진이 코드를 읽을 때 변수나 함수의 선언 부분을 마치 코드 맨 위로 끌어올리는 것처럼 동작하는 독특한 특징이에요. 그런데 여기서 중요한 점! 선언만 끌어올려지고, 값을 할당하는 부분은 원래 코드 위치에 그대로 남아있답니다. 이게 좀 헷갈릴 수 있는데, 같이 한번 차근차근 살펴볼까요?

1. 만능 해결사? var의 호이스팅

var 키워드로 선언된 변수는 호이스팅이 아주 활발하게 일어나요. 사용자의 이름을 출력하는 간단한 코드를 예로 들어볼게요.

printName(); // 어? 아직 userName 만들기 전인데? -> undefined

var userName = "영수"; // 여기서 이름을 "영수"로 할당

function printName() {
  console.log(userName);
}

분명 printName() 함수를 호출하는 시점에는 userName 변수에 "영수"라는 값을 넣기 전인데, 에러가 나지 않고 undefined가 출력돼요. 이게 왜 그럴까요? 바로 호이스팅 때문이에요! 자바스크립트 엔진은 코드를 이렇게 해석하거든요.

🧐 호이스팅 후 실제 동작 순서 (엔진의 생각)

var userName; // 1. userName 선언 부분을 맨 위로 끌어올려요! (값 할당은 아직 X)

function printName() { // 2. 함수 선언도 통째로 위로!
  console.log(userName);
}

printName(); // 3. 함수 호출! 이때 userName은 선언은 됐지만 값이 없어서 undefined 출력

userName = "영수"; // 4. 원래 위치에서 드디어 값 할당!

신기하죠? 선언만 쏙! 위로 올라가는 거예요.

2. letconst도 호이스팅 된다고요? (feat. TDZ)

"그럼 let이랑 const는 호이스팅 안 되나요?" 하고 궁금하실 수 있어요. 놀랍게도, letconst도 호이스팅이 되긴 해요! 😮 하지만 var랑은 좀 다르게 동작해요. 바로 TDZ (Temporal Dead Zone) 라는 개념 때문인데요, 우리말로는 '일시적 사각지대' 정도로 부를 수 있겠네요.

TDZ는 변수가 선언된 위치부터 실제 초기화(값 할당) 코드 전까지의 구간을 말해요. let이나 const로 선언된 변수는 호이스팅되어서 스코프 최상단으로 올라가긴 하지만, 이 TDZ 구간 안에서는 접근할 수가 없어요. 접근하려고 하면 에러가 퐝!💥 하고 터지죠.

printAge(); // 에러! ReferenceError: Cannot access 'userAge' before initialization

let userAge = 25; // 여기서 userAge 초기화

function printAge() {
  console.log(userAge);
}

이 코드도 엔진은 호이스팅을 하긴 해요.

🧐 호이스팅 후 실제 동작 순서 (엔진의 생각)

let userAge; // 1. userAge 선언도 위로 올라가긴 했어요. 하지만 TDZ 시작!

function printAge() { // 2. 함수 선언도 위로!
  console.log(userAge);
}

// ---- 여기부터 TDZ 구간 ----
printAge(); // 3. TDZ 안에서 userAge에 접근 시도! -> ReferenceError 발생! 🚨
// ---- 여기까지 TDZ 구간 ----

userAge = 25; // 4. TDZ 끝! 여기서부터 userAge에 접근 가능해요.

letconstvar와 달리 선언 전에 접근하면 에러를 내뱉기 때문에, 코드 예측 가능성을 높여주는 더 안전한 방법이라고 할 수 있어요.

3. 착한 호이스팅! 함수 선언식

함수를 만드는 방법 중 '함수 선언식' ( function 함수이름() { ... } 형태) 은 아주 착하게 호이스팅돼요. 선언 부분만 아니라 함수 내용 전체가 통째로 끌어올려진답니다. 그래서 함수를 정의한 코드보다 앞에서 호출해도 아무 문제 없이 잘 돌아가요!

greet(); // "안녕하세요!" (잘 나오네요?)

function greet() {
  console.log("안녕하세요!");
}

// 엔진은 greet 함수 전체를 코드 상단으로 옮겨놓고 실행해요.

이건 정말 편리할 때가 많죠!

4. 어? 이건 왜 안돼? 함수 표현식의 호이스팅

이번엔 '함수 표현식' (변수에 함수를 할당하는 형태) 의 호이스팅을 볼게요. 이건 함수 선언식이랑은 좀 다르게 동작해요. 왜냐하면 함수 표현식은 결국 변수에 함수 값을 할당하는 거라서, 변수 호이스팅 규칙을 그대로 따라가거든요.

var로 선언된 경우

var로 함수 표현식을 만들면, var 변수 호이스팅 규칙에 따라 변수 선언만 위로 올라가고 함수 할당은 제자리에 남아요.

sayHi(); // 에러! TypeError: sayHi is not a function

var sayHi = function() { // 함수를 변수에 할당
  console.log("안녕!");
};

🧐 호이스팅 후 실제 동작 순서 (엔진의 생각)

var sayHi; // 1. sayHi 변수 선언만 위로! (아직 함수가 아니라 undefined 상태)

sayHi(); // 2. sayHi는 함수가 아닌 undefined인데 호출하려고 하니 TypeError! 😭 "함수가 아닌데요?"

sayHi = function() { // 3. 원래 위치에서 함수 할당!
  console.log("안녕!");
};

letconst로 선언된 경우

let이나 const로 함수 표현식을 만들면 어떨까요? 네, 예상하신 대로 let/const 변수 호이스팅 규칙과 TDZ가 적용돼요!

sayHello(); // 에러! ReferenceError: Cannot access 'sayHello' before initialization

let sayHello = function() { // 함수를 변수에 할당
  console.log("Hello!");
};

// TDZ 때문에 초기화 전에 접근하면 ReferenceError가 발생해요!

✨ 정리하며

호이스팅, 처음엔 좀 낯설고 헷갈릴 수 있지만 알고 보면 자바스크립트가 코드를 어떻게 이해하고 실행하는지 엿볼 수 있는 재미있는 특징이에요.

  • var 변수는 선언만 위로 슝~ (값 할당 전에는 undefined)

  • let, const 변수도 선언은 위로 가지만, TDZ 때문에 초기화 전 접근 시 에러! 💥

  • 함수 선언식 (function hi(){}) 은 통째로 위로 슝~ (선언 전에 호출 가능 👍)

  • 함수 표현식 (const hi = function(){}) 은 변수 규칙 따라가요 (var는 TypeError, let/const는 ReferenceError 주의!)

호이스팅 동작 방식을 이해하면 코드에서 예상치 못한 오류를 줄이고, 왜 그렇게 동작하는지 더 깊게 파악할 수 있답니다. 물론 가장 좋은 습관은, 헷갈릴 일 없도록 변수나 함수를 사용하기 전에 미리 선언하고 할당하는 것이겠죠? 😉

0개의 댓글