자바스크립트는 위에서부터 아래로 순차적으로 코드를 해석하는 인터프리터(Interpreter) 언어입니다.
하지만 모든 코드가 순차적으로 동작하는 건 아닌데요, 그 이유는 호이스팅(Hoisting) 이라는 알고리즘이 정의된 함수와 변수들을 모두 찾아서 먼저 선언시키기 때문입니다.
(※ 코드 위치 자체가 끌어올려지는 건 아니며, 렉시컬 환경(Lexical Environment)에 등록되는 것입니다.
렉시컬 환경에는 어떤 스코프 범위에서 사용될 변수와 함수들이 저장되며, 스코프의 개수만큼 생성됩니다.
예를 들어, 함수가 하나 있다면 그 함수 내부의 렉시컬 환경, 그리고 함수 밖의 전역 렉시컬 환경까지 총 두 개가 생깁니다.)
아래의 코드에서는 함수 선언문으로 greet()라는 함수를 만들었습니다.
greet(); // hello
function greet() {
console.log("hello");
}
함수 선언보다 호출을 먼저 했는데도 호이스팅에 의해 정상적으로 동작합니다.
그렇다면 함수 표현식은 어떨까요?
greet(); // ReferenceError: Cannot access 'greet' before initialization
const greet = function() {
console.log("hello");
}
위처럼 함수를 할당한 변수를 함수 표현식이라고 합니다. (화살표 함수로 쓸 수도 있습니다)
그리고 에러가 발생했습니다.
왜일까요?
함수 표현식은 변수의 형태입니다.
그리고 변수는 선언 > 초기화 > 할당의 순서대로 이루어집니다.
앞서 말했듯 호이스팅은 변수를 렉시컬 환경에 등록시킵니다만, 등록시키는 시점은 변수가 선언되는 시점입니다.
let이나 const로 선언한 변수가 렉시컬 환경에 등록될 때, 선언만 되어 있고 초기화와 할당은 안 되어 있다 보니 초기화가 안 되어 있다는 에러가 발생하는 것입니다.
초기화가 되지 않은 이 상태를 흔히 TDZ(Temporal Dead Zone)이라고 합니다.
반면 함수 선언문은 함수가 초기화된 채로 등록되기 때문에 정상적으로 호출이 되는 것입니다.
(+)
var로 선언한 변수 같은 경우에는 선언과 초기화를 동시에 해버려서 값 할당만 안 된 변수가 등록됩니다. 그래서 선언문 전에 호출해보면 undefined가 출력되는 것입니다.
'IT > JavaScript & TypeScript' 카테고리의 다른 글
[JavaScript] 클로저를 통해 코드 최적화(Optimizing)하기 (0) | 2024.04.29 |
---|---|
[JavaScript] 클로저(Closure) (0) | 2024.04.24 |
[JavaScript] ES6 문법을 알아보자 (ECMAScript 2015) (1) | 2024.04.22 |
[JavaScript] 자바스크립트 객체 비교 방법 (0) | 2024.02.23 |
[JavaScript] Promise 객체 (0) | 2024.01.23 |