function count() {
var i;
for (i = 0; i < 10; ++i) {
setTimeout(function() {
console.log(i)
}, 100)
}
}
count(); // ??
이 코드는 대표적인 클로저 예제입니다. 숫자를 0부터 9까지 출력하고 싶지만, 10이 10번 출력됩니다.
setTimeout()에 인자로 넘긴 익명함수는 모두 0.1초 뒤에 호출될 것입니다. 그 0.1초 동안 이미 반복문은 모두 순회하면서 i는 10이 된 상태이고, 익명함수가 호출되면서 10이 저장된 i를 참조하기 때문입니다.
이를 이해하기 위해서는 자바스크립트의 스코프에 대한 개념이 필요합니다. 렉시컬 스코프에 정리가 매우 잘 되어 있으니 참고하세요!
위 코드를 해결하려면 다음과 같은 2가지 방법을 사용하면 됩니다.
- 새로운 스코프를 추가하여 반복마다 값을 저장하는 방식
function count() {
var i;
for (i = 0; i < 10; ++i) {
(function(c) {
setTimeout(function() {
console.log(c);
}, 100);
})(i);
}
}
count();
- ES6에 추가된 블록 스코프를 이용하는 방식
function count() {
'use strict';
for (let i = 0; i < 10; ++i) {
setTimeout(function() {
console.log(i);
}, 100);
}
}
count();
참고자료
꿀같은 자료입니당.