Hoisting
- 사전적의미: 끌어올리다, 들어올리다
- javascript에서 변수가 선언되기 전에 사용 될 수 있다는 것을 의미합니다.
→ 함수 안에 있는 선언들을 모두 끌어올려서 해당 함수 유효 범위의 최상단에 선언.
여기서 유효 범위는 함수 블록 {} 안을 말합니다.
호이스팅의 대상
자바스크립트에서는 ES6에서 도입된 let, const를 포함한 모든 선언을 호이스팅합니다.
변수는 3가지 단계를 거쳐 생성 됩니다.
- 선언 단계 (Declaration Phase): 변수를 변수 객체 (Variable Object)에 등록합니다. 이 변수 객체는 스코프가 참조하는 대상이 됩니다.
- 초기화 단계 (Initialization Phase): 변수 객체 (Variable Object)에 등록된 변수를 위한 공간을 메모리에 확보합니다. 이 단계에서 변수는 undefined로 초기화됩니다.
- 할당 단계 (Assignment Phase): undefined로 초기화된 변수에 실제 값을 할당합니다.
💡 var 키워드로 선언된 변수는 선언 단계와 초기화 단계가 한번에 이루어집니다.
→ 초기화 단계에서 undefined로 초기화되기 때문에 변수 선언문 이전에 변수에 접근해도 에러가 발생하지 않고 undefined를 반환하는 것입니다.
var hoisting Example
<!-- 예제1 -->
callByName(name) // 'My name is '
console.log(name) // undefined
function callByName(name) {
console.log(`My name is ${name}`);
}
var name = 'jay'
/* 아래와 같이 작동 */
var name;
function callByName(name) {
console.log(`My name is ${name}`)
}
callByName(name); // 'My name is '
console.log(name); // undefined
name = 'jay';
<!-- 예제2 -->
CallByName("jay"); // 함수 선언 전에 함수를 호출 -> hoisting 이 되어 잘 작동한다.
function CallByName(name){ // 함수 선언.
console.log(name);
}
//PhoneNumber(123); // 작동하지 않는다
var PhoneNumber = function(number) { // 함수의 선언 방식이 아니기 때문에 hoisting 되지 않는다. (only work on function declaration)
console.log(number);
}
//variables (변수)
console.log(age); // 작동은 되지만 undefined로 뜬다. (hoisting) -> js 가 변수가 선언되었는지는 알고 있는 것이다.
// 변수의 선언만 호이스팅.
var age = 20; //global
console.log(age);
function foo(){
var age = 65; //local
console.log(age); //local print
}
foo();
console.log(age); // global print
💡 반면 let, const 키워드로 선언된 변수는 선언 단계와 초기화 단계가 분리되어 이루어집니다.
→ 따라서, 스코프에 변수를 등록(선언단계)하지만 초기화 단계는 변수 선언문에 도달했을 때 이루어지므로 초기화 이전에 변수에 접근하면 참조 에러(ReferenceError)가 발생하는 것입니다.
let hoisting Example
console.log(name) // ReferenceError
let name = 'jay'
Temporal Dead Zone (TDZ)
- 초기화되지 않은 변수가 있는 곳을 Temporal Dead Zone이라고 합니다.
- let, const 는 초기화 되기 전까지 TDZ에서 대기하게 되고,
- 변수가 초기화되는 순간 TDZ에서 나오게 되며 사용할 수 있게 되는 것입니다.
let value = "out Scope";
function hoisted() {
// value가 TDZ에 영향을 받는 순간
console.log("value", value); // value ReferenceError
let value = "inner scope"; // value가 초기화 됨으로써, TDZ가 끝나게 됩니다.
};
hoisted();
여기서 let 변수가 hoisting 되지 않았다면, ReferenceError가 아닌 outScope가 찍혔을 겁니다.
TDZ는 초기화가 되지 않은 바인딩에 접근할 때, 미리 초기화하라고 에러를 알려주는 역할을 합니다.
참고
'JavaScript' 카테고리의 다른 글
Arrow Functions (2) | 2022.10.04 |
---|---|
[오류 해결] Source Map/devtools에서 소스 맵을 로드하지 못함 (0) | 2022.10.03 |
프론트엔드, javascript 참고 사이트 모음 (0) | 2022.08.15 |
Nullish coalescing operator (??) (0) | 2021.09.21 |