호이스팅
- 변수/함수 선언 시점 이전에 그것에 접근할 수 있는 것.
- 선언이 마치 스코프의 상단으로 끌어올려진 것 같은 현상이다.
- 코드 실행 전, 자바스크립트 엔진이 코드를 스캔하고 코드 내의 변수, 함수 선언에 대한 정보를 실행컨텍스트에 기억한다.
- 이 때, 선언 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 라고 하며, 이 때는 접근할 수 없다.
참고자료