for (var i = 1; i < 6; i++) {
setTimeout(function timer() {
console.log(i);
}, i * 1000);
}
아래와 같이 for문과 같은 범위에 선언한 것과 같다.
var i = 1;
for (...) {
setTimeout(function timer() {
console.log(i);
}, i * 1000);
}
5개의 timer() 함수는 선언할 당시 주변 환경인 전역 EC가 관리하는 변수 i (동일한 변수 i)를 사용하므로, 아래와 같은 결과가 나온다.
6
6
6
6
6
for (let i = 1; i < 6; i++) {
setTimeout(function timer() {
console.log(i);
}, i * 1000);
}
아래와 같이 for문 안의 지역 변수로 선언한 것과 같다.
for (...) {
let i = 1
setTimeout(function timer() {
console.log(i);
}, i * 1000);
}
for (...) {
let i = 2
setTimeout(function timer() {
console.log(i);
}, i * 1000);
}
for (...) {
let i = 3
setTimeout(function timer() {
console.log(i);
}, i * 1000);
}
...
5개의 timer() 함수는 for문 블록마다 관리되는 서로 다른 변수 i를 사용하므로, 아래와 같은 결과가 나온다.
1
2
3
4
5
미션!
var 키워드를 사용하면서 1 2 3 4 5 나오게 하기!
방법 1) 클로저 이용하기
makeTimer 함수를 통해 timer 함수를 생성한다.
makeTimer 함수는 변수 i를 받고, makeTimer 함수 실행 컨텍스트 안에서 관리한다.
그리고 timer 함수는 이 안에서 생성되기 때문에, 해당 i를 참조하게 된다.
i가 1, 2, 3, 4, 5일 때 각각 다른 makeTimer 함수 실행 컨텍스트가 생성되고 그 안에서 timer 함수가 생성되므로, 서로 다른 변수 i에 접근하게 된다는 아이디어로 작성했다.
const makeTimer = function (i) {
return function timer() {
console.log(i);
};
};
for (var i = 1; i < 6; i++) {
setTimeout(makeTimer(i), i * 1000);
}
방법 2) 즉시실행함수 이용하기
함수가 실행되면 실행 컨텍스트가 생긴다. 그러므로 즉시실행함수로 한번 감싸고, 인자로 i를 넘겨주면, 즉시실행함수 실행 컨텍스트 생기고, 그 안에서 변수 i가 관리된다.
for (var i = 1; i < 6; i++) {
(function (i) {
setTimeout(function timer() {
console.log(i);
}, i * 1000);
})(i);
}