호이스팅
hoist라는 단어의 뜻부터 살펴보자.
hoist : (흔히 밧줄이나 장비를 이용하여) 들어[끌어]올리다
호이스팅(Hoisting)은 JavaScript에서 변수 및 함수 선언이 코드의 맨 위로 끌어올려지는 동작이다.
JavaScript에서 호이스팅(hoisting)이란,
인터프리터가 변수와 함수의 메모리 공간을 선언 전에 미리 할당하는 것을 의미합니다.
- MDN docs -
변수와 함수의 선언부가 각자의 현재 스코프 영역 최상단으로 옮겨지는 것
이런식으로 호이스팅을 정의하고있다. 근데 이게 뭔소린지 글만보면 잘 이해가 가지 않는다.
During compile phase, just microseconds before your code is executed,
it is scanned for function and variable declarations. All these functions and variable
declarations are added to the memory inside a JavaScript data
structure called Lexical Environment.
So that they can be used even before they are actually declared in the source code.
- Sukhjinder Arora 's Medium -
컴파일 단계에서, 당신의 코드가 실행되기 몇 마이크로 초 전에, 함수와 변수 선언이 스캔된다.
스캔된 모든 함수, 변수 선언은 Lexical Environment라고 불리는 자바스크립트 데이터 구조 내 메모리에 추가된다.
따라서, 함수, 변수가 소스 코드 내에서 실제로 선언되기 이전부터 사용 할 수 있다.
- Medium 블로그 번역 -
A lexical environment is a data structure that holds identifier-variable mapping.
(here identifier refers to the name of variables/functions,
and the variable is the reference to actual object
[including function object] or primitive value).
- Sukhjinder Arora 's Medium -
자바스크립트 엔진은 코드를 실행하기 전에 Lexical Environment 내에 있는 메모리에 함수, 변수 선언을 추가한다.
Lexical Environment는 "identifier-variable" 매핑 정보를 가지고 있는 데이터 구조이다.
"identifier"는 변수, 함수의 이름을 가리키며, "variable"은 실제 객체 혹은 원시값을 가리킨다.
- Medium 블로그 번역 -
호이스팅 예시
함수 선언식의 호이스팅
함수 선언식은 정상적으로 호이스팅이 되어서 helloworld() 가 위에있음에도
밑의 함수 선언을 끌어올려서 정상적으로 helloworld 를 출력했다.
helloWorld(); // Hello World!
function helloWorld(){
console.log('Hello World!');
}
lexicalEnvironment = {
helloWorld: < func >
}
함수 표현식의 호이스팅
하지만 함수 표현식은 타입에러가 떳는데 이는 helloworld 가 함수가 아니라 변수로 인식 되기 때문이다.
그리므로 함수표현식의 경우는 호이스팅이 되지 않는다.
helloWorld(); // TypeError: helloWorld is not a function
var helloWorld = function () {
console.log("Hello World!");
};
helloWorld(); // ReferenceError: Cannot access 'helloWorld' before initialization
const helloWorld = function () {
console.log("Hello World!");
};
그러므로 함수표현식을 사용하기 위해서는
var helloWorld = function(){
console.log('Hello World!');
}
helloWorld(); // Hello World!
이런식으로 사용해야한다.
var의 호이스팅
var는 undifined 에러가 뜬다.
console.log(a); // undefined
var a = 3;
lexicalEnvironment = {
a: undefined
}
실제로는 이런식으로 작동이 됨
var a;
console.log(a); // undefined
a = 3;
let,const의 호이스팅
let , const는 레퍼런스 에러가 뜬다.
console.log(a); // ReferenceError: Cannot access 'greeting' before initialization
let a = 3;
실제로 작동되는 코드
let a;
console.log(a); // undefined
a = 3;
---------------------------------------------------------------------------------------
console.log(a); // ReferenceError: Cannot access 'greeting' before initialization
const a = 3;
실제로 작동되는 코드
const a;
console.log(a); // SyntaxError: Missing initializer in const declaration
a = 3;
자바스크립트에서 모든 선언(함수, var, let, const, class ..)은 hoist된다.
var 선언이 undefined로 초기화되는 반면, let과 const 선언은 uninitialized로 남아있다.
let, const의 초기화는 오직 자바스크립트 엔진 작동 중 lexical binding(할당)이 발생했을 때에만 이루어진다.
이는 엔진이 소스 코드 내에서 let, const가 선언된 장소에서 그 값을 평가하기 전까지는
당신이 변수에 접근할 수 없다는 것을 의미한다.
변수의 생성과 초기화 사이의 기간에 접근 할 수 없는 것을 "Temporal Dead Zone"이라고 한다.
class 선언의 호이스팅
let peter = new Person("Peter", 25);
// ReferenceError: Cannot access 'Person' before initialization
console.log(peter);
class Person {
constructor(name, age) {
this.name = name;
this.age = age;
}
}
실행되기 위해선 이렇게 코드를 작성해야한다.
class Person {
constructor(name, age) {
this.name = name;
this.age = age;
}
}
let peter = new Person("Peter", 25);
console.log(peter); // Person { name: 'Peter', age: 25 }
컴파일 단계
lexicalEnvironment = {
Person: <uninitialized>
}
코드 실행시
lexicalEnvironment = {
Person: <Person object>
}
class 표현식의 호이스팅
let peter = new Person("Peter", 25);
// ReferenceError: Cannot access 'Person' before initialization
console.log(peter);
let Person = class {
constructor(name, age) {
this.name = name;
this.age = age;
}
};
실행되는 표현식
let Person = class {
constructor(name, age) {
this.name = name;
this.age = age;
}
};
let peter = new Person("Peter", 25);
console.log(peter); // Person { name: 'Peter', age: 25 }
'cs 공부' 카테고리의 다른 글
| Promise란 무엇인지 설명해주실 수 있을까요? (0) | 2023.10.15 |
|---|---|
| var, let, const 에 대해 설명해주실 수 있을까요? (0) | 2023.10.15 |
| Node.js의 이벤트 루프란 무엇이고 왜 필요하며 어떻게 작동하는지 아는 만큼 설명해주실 수 있을까요? (0) | 2023.10.15 |
| Node.js는 non-blocking, asynchronous 기반 JS 런타임입니다. 이에 대해 아는 만큼 설명 (1) | 2023.10.15 |
| Node.js는 single-threaded 기반 JS 런타임입니다. 이에 대해 설명해주세요 (1) | 2023.10.15 |