호이스팅이란 코드를 실행하기 전에, 변수 선언/ 함수 선언에 대한 메모리 공간을 미리 할당해 두는 것을 말한다.
변수 선언/ 함수 선언은 런타임 이전에 먼저 실행되는데,
변수 선언/ 함수 선언이 코드의 선두로 올려진것 처럼 동작하는 자바스크립트 고유의 특징이다.
#1. 변수 호이스팅
- 변수 선언시, 변수 선언문이 코드의 선두로 끌어올려진 것처럼 동작하는데 이를 함수 호이스팅이라고 한다.
- var, let, const 모든 키워드로 선언 시, 변수 호이스팅은 발생하지만, 각각의 출력 형태는 약간 상이하다.
1. var로 변수 선언시 ... > undifined로 초기화.
- var 키워드로 선언한 변수는 런타임 이전에 변수 호이스팅에 의해 선언되고, undifined 값으로 초기화가 진행된다.
console.log(score); // undefined
var score; // 1. 변수 선언
score = 80; // 2. 값의 할당
console.log(score); // 80
2. let, const 로 선언시 ... > 변수를 초기화 하지 않음
- let, const 키워드로 선언한 변수는 변수 호이스팅이 발생하지 않는 것처럼 동작한다. (하지만 값이 undifined로 초기화 되지 않을 뿐, 호이스팅은 발생하긴 한다.)
1) let
- let 키워드로 선언한 변수는 '선언단계' 와 '초기화 단계'가 분리되어 진행된다.
- 런타임 이전에 자바스크립트 엔진에 의해 암묵적으로 선언단계가 먼저 실행되지만, 초기화 단계는 변수 선언문에 도달했을 때 실행된다.
- 만약 초기화 단계가 실행되기 이전에 변수에 접근하려고 하면 참조에러가 발생한다.
- 스코프의 시작지점부터 초기화 시작 지점까지 변수를 참조할 수 없는 구간을 일시적 사각지대 라고 부른다.
// 런타임 이전에 선언 단계가 실행된다. 아직 변수가 초기화 안됌
// 초기화 이전의 일시적 사각지대에서는 변수를 참조할 수 없다.
console.log(foo); // 결과 : caught ReferenceError: foo is not defined 에러남
let foo; // 1. 변수 선언
console.log(foo); // 결과 : undifined
foo = 1; // 2. 값의 할당
console.log(foo) // 결과 : 1
2) const
- const 또한 호이스팅이 발생하지 않는것 처럼 동작한다.
console.log(foo2);
const foo2 = 5; // 결과 : foo2 is not defined
#2. 함수 호이스팅
- 함수 또한, 함수 선언문이 코드의 선두로 끌어올려진 것처럼 동작하는데,
함수 호이스팅은 함수를 함수 선언문(function 함수명()) 으로 정의할때 발생한다.
만약, 함수를 함수 표현식(var 변수명 = function함수명()) 으로 정의 했다면, 이때는 변수 호이스팅이 발생한다.
1. 함수 선언문으로 함수를 정의하면 ... > 함수 호이스팅 발생
① 런타임 이전에 함수 객체가 먼저 생성
② 자바스크립트 엔진은 함수 이름과 동일한 이름의 식별자를 암묵적으로 생성
③ 생성된 함수 객체를 생성한다.
- 따라서 함수 선언문 이전에 함수를 참조할 수 있으며 호출할 수도 있다.
- 이처럼 함수 선언문이 코드의 선두로 끌어올려진 것처럼 동작하는 자바스크립트의 고유의 특징을 함수 호이스팅이라고 한다.
catName("클로이");
function catName(name) {
console.log("제 고양이의 이름은 " + name + "입니다");
}
// 결과 : 제 고양이의 이름은 클로이입니다
2. 함수 표현식으로 함수를 정의하면 ...> 변수 호이스팅 발생
① var 키워드로 선언된 변수는 undifined로 초기화
② var 키워드를 사용한 변수 선언문 이전에 변수를 참조하면 변수 호이스팅에 의해 undifined로 평가.
- 변수 할당문의 값은 할당문이 실행되는 시점, 즉 런타임에 평가되므로 함수 표현식의 함수 리터럴 할당문이 실행되는 시점에 평가되어 함수 객체가 된다.
- 따라서 함수 표현식으로 함수를 정의하면 함수 호이스팅이 발생하는 것이 아니라 변수 호이스팅이 발생한다.
- 아래와 같이 정의하면 잘 작동하는 실행문이
var catFunc2 = function catName(name) {
console.log("제 고양이의 이름은 " + name + "입니다");
}
catFunc2("나비")
// 결과 : caught TypeError: catFunc2 is not a function 에러남
- 함수 호이스팅을 생각하며, 아래와같이 정의하면 의도대로 동작하지 않으므로! 꼭 함수 표현식으로 정의한 함수는 반드시 함수 표현식 이후에 참조 또는 호출해야한다.
catFunc2("나비")
var catFunc2 = function catName(name) {
console.log("제 고양이의 이름은 " + name + "입니다");
}
// 결과 : caught TypeError: catFunc2 is not a function 에러남
한편, 함수 호이스팅은 함수를 호출하기 전에 반드시 선언해야한다는 당연한 규칙을 무시한다.
이 같은 문제때문에 json창안자 더글라스 크락포드는 함수 표현식을 사용을 권장한다.
* 참고자료
https://developer.mozilla.org/ko/docs/Glossary/Hoisting
이웅모. 『모던 자바스크립트 Deep Dive』. 위키북스, 2020
'Study > JavaScript' 카테고리의 다른 글
[JavaScript] ... Spread Operator = 괄호 벗겨주세요 (0) | 2023.06.20 |
---|---|
[JavaScript] 문자조작에 유용한 tagged literals (0) | 2023.06.19 |
[JavaScript] this (0) | 2023.05.02 |
[javascript 메서드 정리] 스크롤 이동 메서드 window.scroll() VS window.scrollTo() VS window.scrollBy() (0) | 2023.03.15 |
parseInt()와 Number() 차이점 (0) | 2022.08.04 |