호이스팅
선언문이 스코프의 어디에 있는지에 따라 스코프에 변수가 추가되는 과정의 차이가 있다.
4.1 닭이 먼저냐 달걀이 먼저냐
Javascript 코드가 위에서부터 한줄한줄 실행되지 않는다.
코드 예제 1
a = 2;
var a;
console.log(a); // 2
원본 코드
var a;
a = 2;
console.log(a); // 2
컴파일 결과
코드 예제 2
console.log(a); // undefined
var a = 2;
원본 코드
var a;
console.log(a);
a = 2;
컴파일 결과
위 두가지 예제를 이해 했는가?
4.2 컴파일러는 두번 공격한다.
컴파일 과정에서 선언문을 찾아 적절한 스코프와 연결한다.
렉시컬 스코프의 핵심이다.
var a = 2;
는 사실 아래 두개로 나뉜다.
- var a
- a = 2;
var a는 컴파일 단계에서 처리되고
a = 2; 는 실행 단계에서 처리된다.
따라서 var a 와 같이 선언문이 위로 끌어 올려졌다고 얘기하는 것이다.
이를 호이스팅 이라고 한다.
선언문만 끌어 올려지고, 다른 것들은 그대로 남아있게 된다.
함수 예제 1
foo();
function foo() {
console.log(a); // undefined
var a = 2;
}
foo 함수는 아래에 선언되어 있지만 호출 할 수 있다.
근데 저렇게 되면 foo의 내용은 아래 그대로 남아있어서 undefined 가 되어야 되지 않은가?
호이스팅은 스코프별로 다르게 동작한다.
foo(); // TypeError
bar(); // ReferenceError
var foo = function bar() {
// ...
}
원본 코드
var foo;
foo();
bar();
foo = function() {
var bar = ...self...
}
컴파일 코드
4.3 함수가 먼저다
함수와 변수 모두 호이스팅이 된다.
그러나 함수가 더 먼저 끌어올려진다.
foo(); // 1
var foo;
function foo() {
console.log(1);
}
foo = function {
console.log(2);
}
원본 코드
function foo() {
console.log(1);
}
foo(); // 1
foo = function() {
console.log(2);
}
컴파일 코드
var foo가 중복 선언문이라 그중에 함수 선언문이 먼저 끌어 올려진것을 볼 수 있다.
foo(); // 3
function foo() {
console.log(1);
}
var foo = function() {
console.log(2);
}
function foo() {
console.log(3);
}
위의 코드에선 함수로 선언된 foo가 중복되므로 가장 아래 있는 foo로 덮어 씌워진다.
foo(); // "b"
var a = true;
if (a) {
function foo() {
console.log("a");
}
} else {
function foo() {
console.log("b");
}
}
근데 이거 동작 안하는뎅...?? 뭐지;;
4.4 정리하기
var a = 2; 는 하나의 구문이 아니라 var a와 a = 2 라는 구문이 합쳐진 것이다.
컴파일 단계에서 var a를 처리하고, 런타임에 a = 2가 실행된다.
선언문은 어디서 나타나든 실행 전에 먼저 처리되는 호이스팅이 된다.
선언문 자체는 옮겨지지만 함수 표현식의 대입문은 올라가지 않는다.
중복선언을 조심하자
'개발 > Javascript' 카테고리의 다른 글
[You don't know JS] Part2 - 부록a. 다양한 환경의 자바스크립트 (0) | 2020.09.06 |
---|---|
[You don't know JS] Part2 - 5장. (0) | 2020.09.06 |
[You don't know JS] Part2 - 2장. 함수 vs 블록 스코프 (0) | 2020.09.06 |
[You don't know JS] Part2 - 2장. 렉시컬 스코프 (0) | 2020.09.06 |
[You don't know JS] Part2 - 1장. 스코프란 무엇인가 (0) | 2020.09.06 |