[Javascript] 호이스팅이란? (feat. var, let, const, var가 똥인 이유)

profile
마릴린벅시
2023. 2. 19. 12:59개발

 

호이스팅이란?

호이스팅은 끌어올리다 라는 뜻을 가지고 있다. 자바스크립트 엔진이 코드를 실행하기 전, 변수, 함수, 클래스의 선언문을 끌어 올리는 것을 말한다.  변수의 선언과 초기화를 분리한 후, 선언만 코드의 최상단으로 끌어 올린다.

console.log(a); // undefined
var a = 0;

위 코드에서 변수 a를 선언하기도 전에 콘솔로 출력을 했더니 undefined이 출력되었다. 엥? 변수 a가 없을 때 콘솔에 찍었다면 Uncaout ReferenceError: a is not defined 에러가 떠야하는 것 아닌가? 싶다. 이것이 가능한 이유는 변수가 호이스팅 되었기 때문이다.

undefined는 변수가 선언되었지만 값이 할당되지 않은 경우에 대한 기본 값이다. a에 0이 할당되었다는 사실은 빼고, a가 선언되었다는 사실만 가장 위로 끌어올려주었기 때문에 에러는 발생하지 않고, undefined이 출력된 것이다.

//함수의 호이스팅은 함수의 선언문 전에도 호출이 가능하게 해줌.

print();

function print() {
  console.log('Hello!');
}
함수를 밑에 선언했는데도 위, 아래 어디서 함수를 호출하더라도 에러 없이 함수가 수행되는 이유다.

 

let, const 선언은 호이스팅이 되지 않는다?

정답은 호이스팅이 된다. let, const도 var와 같이 호이스팅에 의해 변수 선언문이 실행되기 이전에도 이미 존재하지만, let, const는 var와 달리 Temporal Dead Zone(TDZ)에 놓여있게 된다. TDZ에 있는 변수는 선언문을 실행하여 변수에 값이 할당되기 전까지는 변수에 접근하려 할 때 Reference Error가 발생한다. (class도 TDZ이 있어서 let, const와 동일하게 동작한다.)

console.log(x); // Uncaught ReferenceError: Cannot access 'x' before initialization 
let x = 1;

즉, 변수가 선언된 위치에서 초기화가 이루어지기 전까지 변수에 접근하면 TDZ에 놓인 것으로 변수를 사용할 수 없다고 보면 된다.

var는 TDZ가 없다. 때문에 값이 할당되지 않은 상태에서도 변수를 사용했을 때 에러가 발생하지 않아서 추적하기 어려운 다양한 에러를 발생시킬 가능성이 있다. 이것이 let, const 사용을 권장하는 이유이다.

 

주의사항

선언문으로 작성된 함수는 호이스팅이 되어 어디서도 사용이 가능하지만 표현식으로 작성된 함수는 다르다. 먼저 선언식 함수와 표현식 함수의 모양을 살펴보자.

// 선언식 함수
foo(); // "Hello"
function foo() {
  console.log("Hello");
}


// 표현식 함수
foo(); // Uncaught TypeError: foo is not a function 
var foo = function() {
  console.log("Hello");
};
 
표현식 함수는 변수에 함수를 할당하는 형태로 만들어진다. 그렇다면 표현식 함수를 담은 변수 foo가 호이스팅이 될 때, foo는 undefined이다.  undefined은 함수가 아니므로, 실행하려고 하면 is not a function 에러가 발생한다.
 

추가 : var를 사용하지 않는게 좋은 이유

//var의 특징

// 1. 변수 선언하는 키워드 없이 선언 & 할당이 가능함
// 선언인지, 재할당인지 구분하기 어려움
something = '똥';
console.log(something); //똥

//2. 똑같은 이름으로 중복선언이 가능함
var poo = '똥2'
var poo = '똥3'
console.log(poo) //똥3

// 3. 블럭 레벨 스코프가 안 됨. 글로벌 변수와 동일하게 작동함
var apple = '사과';
{  
  var apple = '애플'
}
console.log(apple) //애플


// 4. 함수 레벨 스코프만 지원 됨
function example(){
  var dog = '개'
}
console.log(dog); // Uncaught ReferenceError: dog is not defined

 

 

 

반응형