我尝试创建多个setIntervals并存储它们(稍后清除),但是当我这样做时,最后一个setInterval会覆盖前一个,对每个先前的setInterval执行一次,但内容相同。 / p>
带有奇怪行为的代码段:
var timeoutFunctions= {};
function log_on_console(text){
console.log(' > > > inside function : '+text)
}
$( document ).ready(function() {
for (i = 0; i < 5; i++) {
console.log(' > > > before function : '+i)
timeoutFunctions[i] = setInterval(function(){log_on_console(i)}, 2000);
}
});
&#13;
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
&#13;
控制台上的输出是:
" > > > before function : 0" js:21:6
" > > > before function : 1" js:21:6
" > > > before function : 2" js:21:6
" > > > before function : 3" js:21:6
" > > > before function : 4" js:21:6
" > > > inside function : 5" (5) js:16:2 //(this one is the "problem")
我正在考虑这样的事情:
" > > > before function : 0" js:21:6
" > > > before function : 1" js:21:6
" > > > before function : 2" js:21:6
" > > > before function : 3" js:21:6
" > > > before function : 4" js:21:6
" > > > inside function : 0" js:16:2
" > > > inside function : 1" js:16:2
" > > > inside function : 2" js:16:2
" > > > inside function : 3" js:16:2
" > > > inside function : 4" js:16:2
那么,为什么最后一个setInterval(function(){log_on_console(i)}, 2000)
会覆盖前四个?
答案 0 :(得分:5)
这里的功能:
timeoutFunctions[i] = setInterval(function(){log_on_console(i)}, 2000);
...对i
变量有持久引用,而不是创建函数时其值的副本。所以它使用的值i
具有的名称。
如果您想在创建函数时将i
的值刻录到函数中,可以使用Function#bind
:
timeoutFunctions[i] = setInterval(function(val){log_on_console(val)}.bind(null, i), 2000);
或更直接作为您的匿名函数,只需调用log_on_console
:
timeoutFunctions[i] = setInterval(log_on_console.bind(null, i), 2000);
Function#bind
返回一个函数,该函数在调用时将调用原始函数,并将this
设置为您给出的第一个参数bind
,并传递任何其他参数。由于您的函数未使用this
,因此我只使用null
作为该arg。 E.g:
function foo(a) {
console.log("a = " + a);
}
var f = foo.bind(null, 1);
f();
告诉我们:
a = 1
旁注:您的代码会成为The Horror of Implicit Globals的牺牲品,因为您未在任何地方声明i
。
答案 1 :(得分:1)
使用closure()
$(document).ready(function () {
for (var i = 0; i < 5; i++) {
console.log(' > > > before function : ' + i)
(function (curent) {
timeoutFunctions[curent] = setInterval(function () {
log_on_console(curent)
}, 2000);
})(i)
}
});