2012-07-06 138 views
2
var data = [{offset: 2000, str:'foo'}, {offset: 4000, str:'bar'}]; 

for (var i=0; i<data.length; i++) { 
    var x = data[i]; 
    setTimeout(function(){printStuff(x.str)}, x.offset); 
} 

function printStuff(str) { 
    console.log(str); 
} 

我期待得到printStuff('foo')在2000毫秒偏移和printStuff('bar')在4000毫秒偏移,而是它打印“栏”两次。我不知道发生了什么,请帮忙。参数JavaScript回调函数

+0

这是一个范围问题;当你的'printStuff'终于运行时,'x'已被重新分配给'{offset:4000,str:'bar'}' – jackwanders 2012-07-06 14:22:21

回答

3

这样做:

for (var i = 0; i < data.length; i++) { 
    (function (x) { 
     setTimeout(function() { 
      printStuff(x.str) 
     }, x.offset); 
    })(data[i]); 
} 

你的问题是,X在封闭已变更的函数被调用。

2

您可以使用的功能迭代,让一个免费的封闭:

data.forEach(function(x) { 
     setTimeout(printStuff.bind(null, x.str), x.offset); 
}); 

垫片对所有的情况下,过时的歌曲,支持是必需的:

forEach

bind

+0

我不知道这个新的和有趣的功能。你对兼容性(包括手机)有精确吗? – 2012-07-06 14:34:42

+0

@dystroy兼容性和用户自制代码使这些功能在不受支持的浏览器中可以在我给出的链接中找到。大概在2009年12月之后制作/修补的任何浏览器都应该支持它们。 – Esailija 2012-07-06 14:35:57

0

setTimeout不阻止代码继续执行,因此循环完成,并在时间setTimeout执行回调,'x'的最新值是data数组中的第二个对象。