호이스팅(Hoisting)
호이스팅이란 변수 선언문이나 함수 선언문등 모든 선언문이 해당 Scope의 선두로 옮겨진 것처럼 동작하는 특성을 말한다. 즉 선언문은 할당되기 이전에 참조가 가능하다.(undefiend)
변수 자체(변수의 할당된 값)를 끌어올리는게 아니라, 변수의 선언부(선언과 초기화-undefined)만 끌어올린다.
예제)
console.log(a);
var a = 5;
위 코드는 아래처럼 변경된 것처럼 실행된다.
var a; // 변수를 선언만 했기 때문에 a 에는 undefined 값이 들어가 있게 된다.
console.log(a); // 따라서 undefined가 출력된다.
// var 선언은 문서(또는 함수)가 시작될 때 처리되기 때문에
// var 로 선언한 변수는 어디서든지 참조가 가능하다.(전역 변수)
// 다만 변수에 할당이 되기 전까지는 undefined값을 가지고 있다.
a = 5; // 여기서 값이 undefined에서 5로 할당이 이뤄지게 된다.
즉 var a = 5;
라고 선언과 할당를 했다면 var a;
를 끌어올려둔 후(선언과 초기화 까지만) 원래 있던 자리에서 a = 5;
로 할당이 이뤄진다.
선언은 호이스팅 되지만 할당은 호이스팅 되지 않는다.(참고)
modern(현대의) javascript 에서는 var를 쓰지 말아야 한다. 이것은 legacy(오래전의) javascript 에서만 볼 수 있는 변수 키워드이다. 모던한 javascript 에서는 const, let만 사용하고, 호이스팅의 TDZ(Temporal Dead Zone - 일시적인 사각 지대)을 조심하라.
TDZ(Temporal Dead Zone - 일시적 사각 지대)
const test = 'test';
function a() {
console.log(test);
let test = 5;
}
a();
이런 코드가 있다. 실행하면 ReferenceError: Cannot access 'test' before initialization
에러를 마주하게 된다. 즉 test 변수를 초기화 하지 않았기 때문에 접근할 수 없단다.
호이스팅이 일어나지 않는다면 함수 안에서
console.log(test);
부분에test
라고 찍혀야 정상이다.호이스팅이 일어났다면 당연히
undefined
가 찍혀야 정상일테다.const test = 'test'; function a() { let test; // undefined console.log(test); test = 5; } a();
호이스팅과 TDZ
TDZ는 변수의 선언부터 변수에 할당되는 부분을 만나기 전까지 형성되는 구간이다.(참고)
const test = 'test';
function a() {
let test; // 호이스팅에 의한 변수 선언
// 변수가 선은은 되었지만 아직 초기화 구문을 만나지 못했다.
// 즉 아래 tset = 5; 로 할당이 이뤄지기 전까지 TDZ가 형성되게 된다.
// 따라서 여기에서 오류가 발생하게 된다.
console.log(test);
test = 5; // 변수의 할당
}
a();
정리(2020.03.26 추가)
var 키워드의 경우 선언(Variable Object 에 등록)과 초기화가 동시에 일어난다. 여기서 초기화란 메모리에 공간을 확보하고 undefined 값으로 할당하는 과정까지이다.
하지만 let, const 키워드는 선언과 초기화가 분리되어 일어난다. 즉 선언을 하면 Variable Object에 등록은 되지만 실제 초기화는 선언문이 있는 곳에서 일어나게 된다. 여기에서 TDZ가 일어나게 되는 것이다.
정리 2 - 함수 호이스팅의 경우
함수 선언문의 경우
함수 선언문으로 정의된 함수는 자바스크립트 엔진이 스크립트가 로딩되는 시점에 바로 초기화를 하고 이를 VO(variable object)에 저장한다. 즉 함수 선언, 초기화, 할당이 한 번에 이뤄진다.(이것이 변수와는 다른 점이네.) 그렇기 때문에 함수 선언의 위치와는 관계없이 소스 내 어느 곳에서든 호출이 가능하다.
let res = square(5);
function square(number) {
return number * number;
}
함수 표현식의 경우
함수 표현식은 함수를 변수에 저장하기 때문에 변수 호이스팅이 발생한다. 이는 위 정리 1번을 보면 된다.
자바스크립트의 권위자인 더글러스 크락포드는 호이스팅 같은 문제로 인해 함수 선언식 보다는 함수 표현식만을 사용할 것을 권고한다고 한다.
함수 호이스팅이 함수 호출 전 반드시 함수를 선언하여야 한다는 규칙을 무시하므로 코드의 구조를 엉성하게 만들 수 있다고 지적했다.
함수 선언문으로 함수를 정의하면 사용하기에 쉽지만 대규모 애플리케이션을 개발하는 경우 인터프리터가 너무 많은 코드를 변수 객체(VO)에 저장하므로 애플리케이션의 응답속도는 현저히 떨어질 수 있으므로 주의해야 할 필요가 있다.
결론
변수, 함수, 클래스 등은 사용하기 전에 필히 정의하고 할당한 후 사용하자.
참고자료
'TIL' 카테고리의 다른 글
[tailwindcss]폰트 클래스 삽입 (3) | 2020.05.25 |
---|---|
객체 순회/배열 순회 (0) | 2020.03.27 |
자바스크립트 예약어 (0) | 2020.03.27 |
mongodb - projection (0) | 2020.03.20 |
[TIL]2020.03.06 (0) | 2020.03.06 |