호이스팅을 공부하기 전에, 우선 자바스크립트 변수 선언 단계 먼저 공부하면 좋습니다.



변수 선언 단계

3단계가 있습니다.

- 선언 단계

  • 변수 객체(Variable Object)에 변수를 등록합니다.

- 초기화 단계

  • 변수 객체에 등록된 변수를 메모리에 할당합니다. 이 과정에서 변수는 undefined로 초기화 됩니다.

- 할당 단계

  • undefined로 초기화된 변수에 값을 할당합니다.

즉, (1)스코프에 변수가 등록되고 (2)변수는 메모리에 공간을 확보하고 undefined로 초기화합니다. (3) 이후 변수 할당문에 도달하면 값의 할당이 이루어집니다.


호이스팅이란?

스코프 안에서는, 어디에서든 변수 선언이 최상위에서 선언된 것과 같습니다.

실제로 코드가 끌어올려지는 것은 아니고, 자바스크립트 파서가 내부적으로 끌어올리는 것입니다.

실제 메모리에서의 변화는 없습니다.

var x = 'outer';

(function() {
	console.log(x);
	var x = 'inner';
})();

x는 ‘outer’가 출력되지 않고, undefined가 출력됩니다.

위 코드는 아래와 같습니다.

var x = 'outer';

(function() {
	var x;
	console.log(x);
	x = 'inner';
})

호이스팅은, 모든 선언문에서 발생합니다.

  • var, let, const, function, class..

TDZ(Temporal Dead Zone)

var 는 호이스팅이 발생하고, letconst 는 호이스팅이 발생하지 않는다고 오해할 수 있지만, 그렇지 않습니다.

letconst 도 호이스팅이 발생합니다.

예시로 확인해보겠습니다.

console.log(a);
var a = 'a'; //undefined
console.log(b);
const b = 'b';	//ReferenceError: Cannot access 'b' before initialization
console.log(c);	//ReferenceError: c is not defined
  • var 키워드는 선언과 초기화가 동시에 일어나기에, undefined가 출력됩니다.
  • const 키워드는 초기화 전에는 접근할 수 없다는 ReferenceError가 발생합니다. 변수 선언이 이루어졌다는 의미이고, 호이스팅이 발생한다는 뜻입니다.


다른 예시를 살펴보겠습니다.

var name = 'park';
{
  console.log(name);	// Uncaught ReferenceError: Cannot access 'name' before initialization
  let name = 'kim';
}

let 으로 선언한 변수가 호이스팅되지않는다면, console.log의 결과는 ‘park’이었을 겁니다.

하지만 let 으로 선언한 변수가 호이스팅 되었기 때문에 에러가 출력되었습니다.


참고 : 블록 레벨 스코프 vs 함수 레벨 스코프

var는 함수 레벨 스코프.

letconst 는 블록 레벨 스코프.

var x = 0;
{
	var x = 1;
	console.log(x);	//1
}
console.log(x);	//1


let y = 0;
{
	let y = 1;
	console.log(y);	//1
}
console.log(y);	//0

Reference

https://poiemaweb.com/js-data-type-variable

https://wonism.github.io/is-let-hoisted/