setInterval覆盖其他setIntervals

Rod*_*Rod 0 html javascript jquery

我正在尝试创建多个setIntervals并存储它们(稍后清除),但是当我这样做时,最后一个setInterval会覆盖前一个,为每个先前的setInterval执行一次,但具有相同的内容.

带有奇怪行为的代码片段:

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);
    }
});
Run Code Online (Sandbox Code Playgroud)
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
Run Code Online (Sandbox Code Playgroud)

控制台上的输出是:

" > > > 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")
Run Code Online (Sandbox Code Playgroud)

我正在考虑这样的事情:

" > > > 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 
Run Code Online (Sandbox Code Playgroud)

那么,为什么最后一个setInterval(function(){log_on_console(i)}, 2000)压倒前四个呢?

T.J*_*der 5

这里的功能:

timeoutFunctions[i] = setInterval(function(){log_on_console(i)}, 2000);
Run Code Online (Sandbox Code Playgroud)

...具有对变量的持久引用i,而不是在创建函数时的值的副本.因此它使用的值i具有调用时的值.

如果你想燃烧i到的功能,当你创建的功能,你可以使用Function#bind:

timeoutFunctions[i] = setInterval(function(val){log_on_console(val)}.bind(null, i), 2000);
Run Code Online (Sandbox Code Playgroud)

或者更直接地作为你的匿名函数只是调用log_on_console:

timeoutFunctions[i] = setInterval(log_on_console.bind(null, i), 2000);
Run Code Online (Sandbox Code Playgroud)

Function#bind返回一个函数,当调用它时,将调用原始函数,并this设置为您给出的第一个参数bind,并传递任何其他参数.由于你的功能没有使用this,我只是用于null那个arg.例如:

function foo(a) {
    console.log("a = " + a);
}
var f = foo.bind(null, 1);
f();
Run Code Online (Sandbox Code Playgroud)

告诉我们:

a = 1

旁注:你的代码正在成为Implicit Globals的恐怖的牺牲品,因为你没有i在任何地方声明.