호이스팅
- 변수/함수 선언 시점 이전에 그것에 접근할 수 있는 것.
- 선언이 마치 스코프의 상단으로 끌어올려진 것 같은 현상이다.
- 코드 실행 전, 자바스크립트 엔진이 코드를 스캔하고 코드 내의 변수, 함수 선언에 대한 정보를 실행컨텍스트에 기억한다.
- 이 때, 선언 TYPE에 따라 기억되는 정보가 달라진다. 따라서 호이스팅 결과도 다르게 나타난다.
TYPE |
HOISTED? |
초기값 |
스코프 |
함수 선언문 |
✅ |
Actual function |
블록(strict mode) |
var |
✅ |
undefined |
함수 |
let & const |
❎ |
TDZ(uninitialized) |
블록 |
함수 표현식/화살표 함수 |
var, let, const 선언 방식에 영향을 받는다. |
var
선언방식의 경우 선언과 동시에 초기화되므로, undefined
의 값을 가지고 코드가 실행된다.
let
과 const
의 경우 선언시점 이전까지 초기화 되지 않기 때문에, 접근할 수 없다. 이런 이유로 호이스팅이 적용되지 않는 것처럼 보일 수 있다.
- 스코프의 시작점부터
let
, const
로 선언되기 직전까지 초기화되지 않은 값을 가지는 영역을 TDZ
(Temporal Dead Zone) 이라고 한다.
TDZ (Temporal Dead Zone)
- 코드 실행 전
Creation Phase
단계에서, let
과 const
로 선언된 것이 '있다는 것'은 알고 있는 상태.
- 하지만, 선언 시점 전까지 초기화 되지 않는다.
console.log(x); //Uncaught ReferenceError: Cannot access 'x' before initialization at...
const x = 1;
- 위 예제와 같이 선언이 되지 않은 것과는 차이가 있다.
TDZ
는 에러 방지 및 에러의 발견을 쉽게할 수 있도록 도와주고, ES6에 도입된 const
(상수 선언)이 가능하도록 만든다. const
의 경우 한 번 선언되면 값을 재할당 할 수 없기 때문에, var
처럼 undefined
→ value
로 재선언 할 수 없다.
Example
if(!number) deleteCart();
var number = 10;
function deleteCart() {
console.log('카트가 비었습니다.');
}
if(!number)
부분은 number
가 falsy value
일 경우에만 deleteCart( )
를 실행하도록 되어있다.
- 하지만
var
선언방식의 호이스팅으로 인해 number
는 선언 이전 시점까지 undefined
가 할당되어 있다.
- 따라서 if 구문의
number
가 undefined가 아닌 값이기 때문에 위와 같은 결과가 나오는 것이다.
- 이러한 상황을 방지하기 위해서는...
- 되도록
const
를 사용하여 선언하고, 추후 재할당이 필요할 경우에는 let
을 사용한다. (var
사용 지양)
- 가능하면 스코프 상단에 함수를 포함한 모든 선언을 작성한다. 가독성을 높이고 에러를 줄이는 Clean Code 작성에 도움이 된다.
- 또한
var
로 선언된 변수는 window
전역 객체에 프로퍼티를 생성하지만, let
과 const
는 그렇지 않다는 차이가 있다.
정리
- 호이스팅은 변수/함수 선언 시점 이전에 해당 스코프 내에서 접근 가능한 현상을 말한다.
const
와 let
은 호이스팅이 일어나지 않는 것처럼 보이지만, 선언 시점 이전까지 초기화 되지 않은 것 뿐이다. 이를 TDZ
라고 하며, 이 때는 접근할 수 없다.
참고자료