호이스팅
정의 : 변수와 함수 선언문을 선언된 위치에서 코드의 꼭대기로 올리는 동작
호이스팅을 동작을 한번 코드를 보며 확인해보자.
a = 2;
var a;
console.log(a);
위의 코드에서 var a 라는 변수 선언문이 있다.
JS엔진은 코드를 인터프리팅 하기 전에 컴파일한다.(중요)
컴파일레이션 단계 중 모든 선언문을 찾아 적절한 스코프에
연결해주는 것이 렉시털 스코프의 핵심이다.
고로 위의 코드에서는 아래와 같은 구문으로 나누어진다.
- var a;
- a = 2;
첫번째 구문은 선언문으로 컴파일레이션 단계에서 처리되며,
두번째 구문은 대입문으로 실행 단계 까지 방치된다.
고로 코드는 다음과 같이 처리된다.
var a;
a = 2;
console.log(a);
선언문만 끌어올리고 다른 대입문이나 실행 로직 부분은 제자리에 둔다.
위에서 글로벌 스코프에서만 호이스팅이 동작하는 것 처럼 보이지만,
호이스팅은 각 스코프별로 동작하는 것 또한 중요한 점이다.
function foo() {
console.log(a); // undefined
var a = 2;
}
foo();
위의 코드를 호이스팅이 일어나면 아래의 코드처럼 된다.
function foo() {
var a;
console.log(a); // undefined
a = 2;
}
foo();
함수 선언문은 끌어올려지지만 함수 표현식은 다르다.
a(); // not RefferenceError, but TypeError
var a = function b() {
...
}
변수 확인자 a는 끌어올려져 둘러싼 스코프에 붙으므로 a() 호출은 실패하지 않고,
ReferenceError도 발생하지 않는다.
그러나! a는 아직 값을 갖고 있지 않기에 a()가 undefined 값을 호출해 TypeError라는 오동작을 발생한다.
추가적으로 함수 표현식이 이름을 가져도 그 이름 확인자는 해당 스코프에서 찾을 수 없다.
foo(); // TypeError
bar(); // ReferenceError
var foo = function bar() {
var bar = ...
}
위의 코드는 호이스팅을 적용하면 아래와 같아진다.
var foo;
foo(); // TypeError
bar(); // ReferenceError
foo = function bar() {
var bar;
bar = ...
}
함수가 변수보다 먼저 올려진다
a(); // 1
var a;
function a() {
console.log(1);
}
a = function() {
console.log(2);
}
위의 코드는 아래와 같이 엔진이 해석한다.
function a() {
console.log(1);
}
a(); // 1
a = function() {
console.log(2);
}
var a 가 중복 선언문이라는 점을 주의 해서 보자
var a는 function a() 선언문보다 앞서 선언되었지만, 함수 선언문이 일반 변수 위로 끌어올려졌다.
많은 중복 변수 선언문이 사실상 무시됐지만 중복 함수 선언문은 앞선 것들을 겹쳐 쓴다.
b(); // b 호이스팅 되면 함수가 먼저 선언되며 변수는 밀리기 때문
var a = true;
if(a){
function b() {console.log("a")};
}
else{
function b() {console.log("b")};
}
블록 내 함수 선언은 지양하는 것이 가장 좋다!!!
정리
1. var a = 2는 하나의 구문처럼 보이지만 엔진은 var a (변수 선언문)과 a = 2(대입문) 두 구문으로 보며
첫번째 구문은 컴파일러 단계에서, 두번째 구문은 실행 단계에서 처리한다.
2. 1번이 의미하는 것은 스코프의 모든 선언문은 실행전에 먼저 처리된다.
3. 호이스팅이라는 과정은 선언문 각각 속한 스코프의 꼭대기로 끌어올려지는 작업이다.
4. 함수 표현식의 대입문 등 모든 대입문은 호이스팅 되지 않는다.
5. 중복선언을 조심해서 사용하자.
'JavaScript > You Don't know JS' 카테고리의 다른 글
I don't know JS YET) 함수 vs 블록 스코프 - 2 (0) | 2022.12.23 |
---|---|
I don't know JS YET) 함수 vs 블록 스코프 - 1 (1) | 2022.12.21 |
I don't know JS YET) 렉시컬 스코프 (0) | 2022.12.16 |
I don't know JS YET) 스코프란 무엇인가 (0) | 2022.12.15 |
JS 복습 1주차 / 4. 강제 변환 Coercion (0) | 2022.11.07 |