Jiyong's STUDY
Javascript의 Hoisting과 Scope 본문
test1();
function test1() {
console.log('test1');
}
--
node test.js
test1
--
test1의 선언보다 호출을 먼저 했지만 정상적으로 실행이 된다.
test2();
var test2 = function() {
console.log('test2');
}
--
node test.js
/Users/jiyong/WebstormProjects/study-types/test.js:6
test2();
^
TypeError: test2 is not a function
--
마찬가지로 선언보다 호출을 먼저 했지만 오류가 난다.
두 개의 차이는 일반 함수와 인라인 함수에서 나는 차이긴 하지만, 아무튼 호이스팅이 적용된 결과라고 볼 수 있다.
test2();
let test2 = function() {
console.log('test2');
}
--
node test.js
/Users/jiyong/WebstormProjects/study-types/test.js:6
test2();
^
ReferenceError: Cannot access 'test2' before initialization
--
var를 let으로 변경했을 때의 결과다.
TypeError -> ReferenceError로 에러의 타입이 변경되었다.
var로 선언했을 때에는 test2의 타입이 function이 아니라는 대답이 돌아왔고,
let으로 선언했을 때에는 test2가 이니셜라이징 되기 전에 접근할 수 없다는 대답이 돌아온다.
이 차이를 제대로 확인해보자.
debugger;은 클라이언트에서 javascript 디버깅을 할 수 있게 해주는 키워드다.


a1의 경우에는 함수이고, a2는 var에 함수를 값으로 저장한 것이고, let도 함수를 값으로 저장한 것이다.
즉 a1은 일반 함수, a2와 a3은 인라인 함수이다.
이제 호이스팅이 뭔지 감을 잡을 수 있다. 호이스팅은 선언이 최상단으로 끌어올려지는 것을 말한다.
num = 10;
console.log(num);
var num;
--
node test.js
10
--
이런 식으로 num을 늦게 선언했지만 자동으로 끌어올려진다.
하지만 이런 식으로 코드를 작성하면 문제가 생길 수 있다.
num += 10;
console.log(num);
var num = 0;
--
node test.js
NaN
--
결과는 NaN이 나왔다.
var num = 0;으로 초기화를 진행했고, 거기에 10을 더한 것인데 왜 10이 아니고 NaN이 나올까?
위에서 디버깅을 할 때 var 변수는 undefined로 보이는데 그렇기 때문일까?
undefined + 10 = NaN이다. 아마 그렇기 때문일거다. 자세히 보면,


a: undefined로 나와있다.
a를 선언할 때 var a = 0;으로 했지만 0이 아닌데,


var a = 0;이라는 구문이 실행되어야만 a가 초기화가 된다.
즉 선언만 끌어올리는 것이지 초기화도 같이 하는 것은 아니라는 것이다.
정확히 저 두 줄의 코드는 다음과 같이 실행된다.
var num;
console.log(a);
a = 0;
또한 위에 함수 부분 디버깅에서 let이 Script로 나와 있는 이유는 블록 레벨 스코프가 적용되어 있기 때문이다.
기존의 var은 비 블록 레벨 스코프가 적용되어 있는데 그 차이를 보면,
if (true) {
var a = 1;
let b = 2;
}
console.log(a);
console.log(b);
--
node test.js
1
/Users/jiyong/WebstormProjects/study-types/test.js:7
console.log(b);
^
ReferenceError: b is not defined
--
1은 출력되었다. 즉 a는 접근이 가능했다는 것이다.
b의 경우에는 접근이 불가능했는데, 에러를 확인하면 ReferenceError로 not defined가 되어있다.
블록 레벨 스코프는 쉽게 {} 단위로 짤린다는 이야기인데,
let의 경우에는 if문으로 묶인 부분에 블록 레벨이 적용되어 그 블록 안에서만 사용되고 그 밖에서는 사용이 불가능하다.
다만 var는 블록 밖에서도 사용이 가능했다.
다시 돌아가서, 블록 범위에서의 호이스팅을 알아보면
console.log('before a: %d', a);
if (true) {
var a = 1;
let b = 2;
}
console.log(a);
console.log(b);
--
node test.js
before a: NaN
1
/Users/jiyong/WebstormProjects/study-types/test.js:9
console.log(b);
^
ReferenceError: b is not defined
--
var a는 전체 범위에서 호이스팅이 되는 것이 아니라 블록 단위로 호이스팅이 되는 것을 알 수 있다.
그렇다는 이야기는 var은 그냥 블록의 최상단에 호이스팅이 되는 것이다.
왜냐? 자바스크립트의 코드는 하나의 함수로 취급이 되고, 그 블록 스코프에서 맨 위로 당겨지기 때문에
전체 블록의 최상단에 호이스팅이 된다고 생각해도 된다.
'Web > 자바스크립트' 카테고리의 다른 글
Javascript의 call, apply, bind (0) | 2021.06.29 |
---|---|
Javascript의 this와 call (0) | 2021.06.28 |
클로저(Closure)란? (0) | 2021.06.24 |
Javascript의 실행 컨텍스트 (0) | 2021.05.26 |
Javascript의 함수 (0) | 2021.05.26 |