자바스크립트의 구동방식 중 하나이다.
hoisting? 끌어올리다 hoist+ing.
변수 정보를 수집하는 과정을 이해하기 쉬운 방법으로 대체한 가상의 개념
자바스크립트 엔진이 실제로 끌오올리지는 않지만, 편의상 끌어올린것으로 간주하자는 것!
따라서 코드의 작성순서(위치)가 아니라 코드의 실행 순서(시간)에 의해 형성된다.
호이스팅 문제점을 해결하기 위해 클로저가 사용된다.
📝 호이스팅
코드 실행 전에 식별자들을 해당 스코프 범위의 최상단으로 끌어올려놓은 것처럼 보이는 현상
엔진은 코드가 실행되기 전에 코드 속 이름을 미리 파악한다.
* 식별= 함수, 변수, 클래스, import 등 의 선언문
var, let, const 세타입 모두 호이스팅 되지만, let, const는 호이스팅에서 문제가 발생하는 특징에 영향을 받지 않는다 - TDZ
함수, var 호이스팅
function a(){
console.log(b); //(1)
var b = 'bbb';
console.log(b); //(2)
var b = function b() {};
console.log(b); //(3)
}
a();
원본 코드에서 출력결과를 단순히 예측해보면 (1) 에러 or undefined (2) 'bbb' (3) b함수 - X
정답은 (1) b함수 (2) 'bbb' (3) 'bbb' 결과가 도출된다.
호이스팅을 마친 상태로 가상으로 코드를 구성해보자
function a(){
var b; // 수집대상 1.
function b() {};//수집대상 2.
console.log(b); //(1) 함수b
b = 'bbb'; //변수의 할당부
console.log(b); //(2) bbb
console.log(b); //(3) bbb
}
a();
- 수집대상 1은 변수! 변수는 선언부분만 끌어올린다. 이때 저장공간 확보하고, 공간의 주소값을 변수에 연결해둔다.
- 수집대상 2은 함수! 함수는 전체를 끌어올린다.
- ❗호이스팅이 끝난 상태에서의 함수 선언문은 함수명으로 선언한 변수에 함수를 할당한 것처럼 여길 수 있다.
- `var b = function b() {};`
- 이제 변수 b는 b 함수를 가리기게 된다.
- (1) 변수 b 에 할당된 함수 b를 출력한다
- 변수 b 에 'bbb'를 할당한다. b 함수를 덮어쓴다
- (2), (3) console.log에는 'bbb' 출ㄹ7ㅕㄴ된다.
- 함수 내부 모든 코드가 실행됐으므로 실행 컨텍스트가 콜 스택에서 제거된다.
단점
함수 밖에 var로 변수 할당이 되었을 경우, 호이스팅으로 함수가 최상단으로 끌어올려져 전역변수가 함수 이후에 실행이 된다. → undefined가 들어간다.
let / const 호이스팅
호이스팅에 의해 읽으려고 하면 TDZ의 제약을 받아 `ReferenceError`가 발생한다.
이는 코드를 예측가능하고, 잠재적 버그를 찾아낼 수 있도록 한다.
원본코드에서 /// 호이스팅 된 코드를 보았을때
function a(){
console.log(b); //(1)
let b;
console.log(b); //(2)
b = 'bbb';
console.log(b); //(3)
}
a();
(1) `ReferenceError` (2) undefined (3) 1
단순이 코드를 보았을때 직관적으로 예측가능하게!
실행되는 것을 알 수 있다.
(1)은 TDZ에 의해 에러가 발생하게 된다.
* var일 경우 (1)undefined를 반환한다.
Temporal Dead Zone (TDZ) - 일시적 사각지대
let, const 변수는 초기화하기 전에 읽거나 쓸 수 없다. #참고
초기화 전에 접근을 시도하면 `ReferenceError`가 발생한다.
스코프 맨 위에서 초기화 완료 전까지 변수는 `TDZ에 들어간 변수`라고 표현한다.
📝 전역변수, 지역변수 스코프의 경우
원본코드
var x = 'outer scope';
(function() {
console.log(x); // undefined
var x = 'inner scope';
}());
호이스팅된 코드
var x = 'outer scope';
(function() {
var x;
console.log(x); // undefined
x = 'inner scope';
}());
호이스팅은 스코프 안의 어디서든 변수 선언은 최상위에서 선언된것과 동등하기 때문에
function 밖의 var 선언은 함수 내부에 영향을 주지 못한다.
var은 함수 스코프를 사용하기 때문이다!
❓그렇다면 해당 코드로 let의 경우? `ReferenceError` 발생 → TDZ
☑️ 정리
변수 선언 방식을 어떻게 사용해야 할까?
기본적으로 const를 사용하고, 재할당이 필요한 경우에 let을 사용하는 것이 좋다.
예측 가능한 코드를 쓰기 위해서 var은 최대한 지양하는게 좋다.
const를 쓰면, 호이스팅 문제점 뿐만 아니라 의도치않은 재할당을 방지해주기 때문에 보다 안전하다.
배운점
var을 쓰지말라고만 알고있었는데 다양한 문제점을 파악하게 되었다.
호이스팅에 대해 깊게 이해할 수 있었다.
# 참조
[yocee57] let과 const는 호이스팅 될까?
[Taeseon Kim] const || let || var
[quantumcode] var, let, const 차이점 / 호이스팅이란? / null, undefinded