함수 스코프 : 함수를 경계로 접근 여부가 달라지는 것
function b() {
var a = 1;
}
console.log(b);
<실행 결과>
Uncaught ReferenceError: a is not defined
: 함수 바깥으로 빠져나오면 접근이 되지 않는다.
if(true) {
var a = 1;
}
console.log(a);
<실행 결과>
1
: 함수가 아니므로, 접근이 가능하다.
for (var i = 0; i < 5; i++) {}
console.log(i);
당연히
i = 4
라고 예상되겠지만,i = 4
일 때i++
가 마지막으로 실행되므로i = 5
가 나오게 된다.
블록 스코프 : 블록( {} )을 기준으로 접근 여부가 달라지는 것
(대부분의 언어가 블록 스코프를 갖고 있음)
if(true) {
let a = 1;
}
console.log(a);
<실행 결과>
Uncaught ReferenceError: a is not defined
for (let i = 0; i < 6; i ++) {}
console.log(i);
<실행 결과>
Uncaught ReferenceError: i is not defined
for(let i = 0; i < 6; i++) {
setTimeout(() => {
console.log(i);
}, 2000);
}
<실행 결과>
0
1
2
3
4
5
for(var i = 0; i < 6; i++) {
setTimeout(() => {
console.log(i);
}, 2000);
}
실행 결과
6
6
6
6
6
6
for 문
에서let
을 쓰는 경우 하나의 블록마다i
가 고정된다. (블록 스코프)
※ 스코프는 밖에서 접근하는 것도 제한하지만, 안에 있는 것도 밖으로 나가지 못하도록 차단을 해준다. (따라서i
가 해당 스코프 안에 고정됨)하지만
var
을 쓰는 경우, 함수가 아니므로, 반복문이 매우 빠른 속도로 돌아서 이미i = 6
이 된 상태로setTimeOut
내부의 함수가 실행되게 된다.
함수 스코프로 감싸주어
i
를 고정시킨다!
for(var i = 0; i < 6; i++) {
(function(j) {
setTimeout(() => {
console.log(i);
}, 2000);
})(i);
}
※ 참고 : 함수를 괄호로 감싸서 뒤에 ( )를 붙이면 선언과 동시에 실행할 수 있다.
함수와 함수 바깥에 있는 변수와의 관계
var과 비동기가 만나면 clousre 문제가 발생한다!