호이스팅 이란?
- 호이스팅은 코드를 실행하기전 변수선언/함수선언을 해당 스코프의 최상단으로 끌어올리는 것이 아닙니다.
- 호이스팅은 코드를 실행하기전 변수선언/함수선언을 해당 스코프의 최상단으로 끌어올려진 것 같은 현상을 말합니다.
- 자바스크립트 엔진은 코드를 실행하기 전 실행 가능한 코드를 형상화 하고 구분하는 과정(실행 전 컨텍스트를 위한 과정)을 거친다.
- 자바스크립트 엔진은 코드를 실행하기 전 실행 컨텍스트를 위한 모든 선언(var,int,const,function,class)를 스코프에 등록한다.
- 코드실행 전 이미 변수선언/함수선언이 저장되어 있기에 선언문보다 참조/호출이 먼저 나와도 오류없이 작동한다.
- 실행 컨텍스트는 실행 가능한 코드가 실행되기 위해 필요한 환경을 의미하고 실행되기전 이러한 실행 컨텍스트 과정 (코드를 구분하는 과정)을 거친다.
이런 호이스팅이라는 용어는 자바스크립트 실행 컨텍스트에 의한 위에 설명한 현상을 호이스틍이라고 부른다는 것으로 이해하면 된다. 그 현상이란 선언이 코드 실행 보다 먼저 메모리에 저장되는 과정으로 인한 현상을 말한다
그렇기 떄문에 자바스크립트 실행 컨테스트에 대한 이해하는 것이 호이스팅을 이해하는 데 도움이 된다.
1. 변수 호이스팅 (var, let, const 키워드)
- 자바스크립트의 모든 선언에는 호이스팅이 일어난다.
- 그런데 let, const, class를 이용한 선언문을 호이스팅이 발생하지 않는 것처럼 동자간다.
- var 키워드로 선언된 변수는 스코피의 시작에서 변수의 선언까지 "일시적 사각지대(Temporal Dead Zone:TDZ)에
빠지기 떄문이다.
여기서 중요한 지점은 이 호이스팅이라는 요어는 "선언이 먼저 메모리에 저장되었다" 라는 의미이기 떄문에 즉,
"선언이 끌어올려진다"는 의미이기 때문에 모든 선언은 호이스팅이 일어난다는 말이 참(true)가 된다.
즉, 호이스팅이 파일의 맨 위로 끌어 올려진 것 같은 현상을 의미 할때 선언문 이전에 참조해서 에러를 발생시킨다고
호이스팅이 일어나지 않는 것은 아니라는 것이다.!!
- 그 이유는 정말 선언 자체는 끌어올려진 것이 맞다. (표현하면 그렇고 정확하게는 선언이 코드 실행 전 메모리에 저장되 었다는 의미이다.)
- 그런데 왜 오류가 나는가 하면 var 키워드는 선언과 함께 undefined로 초기화되어 메모리에 저장되는데
let & const는 초기화 되지 않는 상태로 메모리에 저장되기 때문이다. - 초기화 되지 않으면 변수를 참조할 수 없다. 그래서 참조 에러를 일으키는 것이다.
- 호이스팅이 일어나지 않는다면 아래 코드에서 에러가 발생하지 않을 것이다.
- 선언이 호이스팅되었기 때문에 스코프에서 foo를 찾을 수 없는 것이다.!!
let foo = 1; // 이미 선언이 foo가 되어서 블록객체 안에서는 foo를 찾을 수가 없다!!
{
console.log(foo);
let foo = 2;
}
위 예시를 참고하면 크게 이해가 될 것이다.
호이스팅은 '현상'을 의미하는 것이라면 변수 키워드중 var만이 에러 없이 변수 선언에서 상단으로 끌어올려진 것 같은
'현상'이 일어나기 때문에 var만이 호이스팅이 일어난다고 생각할 수 있다.
그러나 위 예시에서 알수 있듯이 자바스크립트 엔진이 동작하는 방식을 알고보면 let키워드에서도 상단으로 끌어 올려진 것 같은 '현상(즉 호이스팅)'이 발생했기 때문에 에러가 발생하는 것이라는 것을 알 수 있었다.
(에러가 난다고 호이스팅이 된 것이 아닌, 호이스팅이 발생했기 때문에 에러가 발생한 것이다)
※ 변수는 어떻게 생성되고, 호이스팅이 이루어 질까?
- 변수는 총 3단계 걸쳐 생성된다.
1단계: 선언 단계 (Declaration phase)
- 변수를 실행 컨텍스트의 변수 객체에 등록한다.
- 이 변수 객체는 스코프가 참조하는 대상이 된다.
2단계: 초기화 단계 (Initialization phase)
- 변수 객체에 등록된 변수를 위한 공간을 메모리에 확보한다.
- 이 단계에서 변수는 undefined로 초기화 된다.
3단계: 할당 단계 (Assignment phase)
- undefined로 초기화된 변수에 실제 값을 할당한다.
var키워드로 선언한 변수는 선언 단계와 초기화 단계가 한번에 이루어진다. 즉, 스코프에 변수를 등록(선언 단계)하고 메모리에 변수를 위한 공간을 확보한 뒤, undefined로 초기화된다. 따라서 변수 선언문 이전에 변수에 접근하더라도
스코프에 변수가 존재하기 때문에 에러가 발생하지 않는다. 다만 undefined를 반환한다.
이후 변수 할당문에 도달하면 비로소 값이 할당된다. let키워드로 선언된 변수는 선언 단계와 초기화 단계가 분리되어
진행된다.
즉, 스코프에 변수를 등록(선언 단계) 하지만 초기화 단계는 변수 선언문에 도달했을 때(코드를 실행 후) 이뤄진다.
초기화 이전에 변수에 접근하려고 하면 참조 에러가 발생한다. 이는 아직 변수 초기화 시작지점까지는 변수를 참조 할 수 없다.
스코프의 시작 지점부터 초기화 시작 지점까지의 구간을 '일시적 사각지대(TemporalDead Zone:TDZ)라고 부른다.
호이스팅의 예시
변수 선언에서의 호이스팅 예시
// 변수 선언을 var 키워드로 아래에서 했기에 선언이 끌어올려저 오류가 나지 않음
text = "Hello"; // 선언이 없으면 var선언과 동일
console.log(text); // 선언없이도 콘솔출력
var text
const text; // 에러남; 주의! 애초에 const는 상수로서 변하지 않는 값이라 재할당이 불가능하다! 그래서 선언과 동시에 할당해야 함
text = "hello"; // 할당을 먼저하고 선언을 한것과 동일하다 그러니 처음에
// 할당하지 못해서 text를 넣어도 출려되지 않는다.
let text;
console.log(text)
함수 선언에서 호이스팅 예시
foo1(); // 함수 선언문에서는 호이스팅이 일어난다.
foo2(); // 함수 표현식이라서 호이스팅이 되지 않는다.
function foo1() {
console.log("Hello");
}
function foo2() {
console.log("world");
}
참고 자료
'프론트 엔드 > Javascript' 카테고리의 다른 글
[Javascript] 얕은 복사(Shallow Copy)와 깊은 복사(Deep Copy) 차이 (0) | 2022.01.16 |
---|---|
[Javscript] 원시 자료형, 참조 자료형 (0) | 2022.01.16 |
[Javscript] Tagged Template Literal (0) | 2022.01.16 |