호이스팅(Hoisting)
인터프리터가 코드를 실행하기 전에 함수, 변수 선언을 선언하고 맨 위로 끌어올린 것처럼 보이는 현상을 말한다. 호이스팅은 함수나 변수를 어디에 선언했던지 간에 필요한 곳에서 자유롭게 사용하기 위해 만들어진 기능이나, 잘못된 값(undefined)을 받아 예기치 못한 버그를 발생시킬 수 있다.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
console.log(a); //undefined
var a = 4;
</script>
</body>
</html>
이처럼 이후에 변수가 선언되었어도, a의 값을 undefined로 초기화하여 값을 불러온다. JavaScript의 변수는 3단계에 걸쳐서 생성한다.
- 선언 단계
스코프와 변수 객체가 생성되고, 변수를 변수 객체에 등록하는 단계이다. 스코프가 변수 객체를 참조한다. 초기화 전까지는 TDZ(temporal dead zone : 스코프의 시작지점부터 초기화 시작 지점까지의 구간)에 존재한다. - 초기화단계
변수 객체 값을 위한 공간을 메모리에 할당한다. 이때 할당되는 값은 undefined로 초기화 된다. - 할당단계
사용자가 undefined로 초기화된 메모리를 다른 값으로 할당하는 단계이다.
여기에서 var의 경우에는 변수 선언 전에 선언단계와 초기화단계를 동시에 진행한다. 그렇기 때문에 변수를 선언하기 전에 호출하면 undefined로 호출되는 호이스팅이 발생한다. let과 const의 경우에는 선언단계와 초기화단계가 분리되어 진행되기 때문에, 호이스팅은 발생하나 메모리가 할당되지 않은 TDZ에 존재하게 되어 참조에러(Reference Error)가 발생한다.
함수의 경우에는 함수선언식은 호이스팅이 발생되고, 함수표현식은 호이스팅 되지 않는다. class의 경우에는 호이스팅은 일어나지만 TDZ에 존재하게 되어 참조에러가 발생한다.
변수 호이스팅
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
//var의 경우 선언과 초기화를 동시에 함.
console.log(a1); //undefined
var a1 = 10;
console.log(a1); //10
// let/const의 경우 호이스팅은 발생하지만 초기화가 되지않아 TDZ에 존재하기 때문에 참조에러가 발생함.
console.log(a2); // ReferenceError: Cannot access 'a2' before initialization
let a2 = 20;
</script>
</body>
</html>
함수 호이스팅
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
//함수 선언식의 경우에는 호이스팅이 된다.
console.log(greet()); // 안녕하세요
function greet(){
return "안녕하세요";
}
// 함수 표현식은 변수가 선언되기 전에 호출할 수 없다.
// var로 선언되었을 경우 변수의 경우 undefined로 초기화되지만, undefined는 함수가 아니기 때문에 TypeError가 뜬다.
console.log(turnon); //undefined
console.log(turnon()); // TypeError: turnon is not a function
var turnon = function turnOn(){
return "켜졌습니다.";
}
</script>
</body>
</html>
클래스 호이스팅
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
// 호이스팅은 일어나지만 TDZ에 존재하게 되어 참조에러가 발생
let class1 = new Class1();
class1.func1(); //ReferenceError: Cannot access 'Class1' before initialization
class Class1{
func1(){
console.log("안녕하세요");
}
}
</script>
</body>
</html>
'Frontend > JavaScript' 카테고리의 다른 글
JavaScript의 getter와 setter 에 대해서 (0) | 2024.07.23 |
---|---|
JavaScript의 for문(for-in | for-of | forEach)에 대해 알아보자 (0) | 2024.07.23 |
JavaScript의 기초 문법 : 배열 (0) | 2024.07.23 |
JavaScript의 기초 문법 : 객체 (0) | 2024.07.22 |
JavaScript의 기초 문법 : 함수 (0) | 2024.07.22 |
JavaScript의 기초 문법 : 제어문 - 반복문(while / for) (0) | 2024.07.19 |
JavaScript의 기초 문법 : 제어문 - 조건문 (if / switch-case) (0) | 2024.07.18 |
JavaScript의 기초 문법 : 연산자 (0) | 2024.07.16 |