我想传递变量setTimeout
函数并对其执行某些操作。当我提醒i
的价值时,它会显示我没想到的数字。我做错了什么?我想要从1到8的日志值。
var end=8;
for (var i = 1; i < end; i ++) {
setTimeout(function (i) {
console.log(i);
}, 800);
}
答案 0 :(得分:11)
解决此问题的标准方法是使用工厂函数:
var end=8;
for (var i = 1; i < end; i ++) {
setTimeout(makeResponder(i), 800);
}
function makeResponder(index) {
return function () {
console.log(index);
};
}
在那里,我们在循环中调用 makeResponder
,并返回一个函数,该函数关闭传递给它的参数(index
)而不是{{1}变量。 (这很重要。如果您刚刚从匿名函数中删除了i
参数,那么您的代码将部分工作,但所有函数在运行时都会看到i
的值,而不是最初安排的时间;在您的示例中,他们都会看到i
。)
更新从以下评论中
...如果我以这种方式调用它
会是正确的吗?8
是的,如果您的目标是让每次通话比最后一次通话晚大约800毫秒,那么这将有效:
我试过了
setTimeout(makeResponder(i),i*800);
,但它无法正常使用
您不会以这种方式使用setTimeout(makeResponder(i),setInterval(i));function setInterval(index) { console.log(index*800); return index*800; }
,并且可能根本不想使用它。
进一步更新:您在下面说过:
我需要先迭代打印8延迟8秒,第二次迭代打印7延迟7秒........打印2延迟2秒...打印0延迟0秒
您只需使用第二次超时再次应用上述原则:
setInterval
我认为你现在拥有了实现这一目标所需的所有工具。
答案 1 :(得分:2)
你的问题是你在i
函数触发后的一段时间内引用变量setTimeout()
,到那时,i
的值已经改变(它已经结束了) for
循环。要使每个setTimeout保持适当的i
值,您必须为每个i
回调单独捕获该值setTimeout()
。
使用工厂函数的上一个答案很好,但是我发现自执行函数比工厂函数更容易键入和跟踪,但两者都可以工作,因为它们都在闭包中捕获你想要的变量,这样你就可以参考了它们在setTimeout回调中的静态值。
以下是自执行函数如何解决此问题:
var end=8;
for (var i = 1; i < end; i ++) {
(function (index) {
setTimeout(function() {
console.log(index);
}, 800);
})(i);
}
要设置超时延迟与i
的值成比例,您可以这样做:
var end=8;
for (var i = 1; i < end; i ++) {
(function (index) {
setTimeout(function() {
console.log(index);
}, index * 800);
})(i);
}
自执行函数传递i
的值,并且包含该值的函数内的参数名为index
,因此您可以引用index
来使用适当的值。
答案 2 :(得分:0)
这不起作用的主要原因是因为setTimeout
设置为在800
之后运行,i
的范围。
执行时i
的值已经改变。因此,无法收到明确的结果。就像TJ说的那样,解决这个问题的方法是通过处理函数。
function handler( var1) {
return function() {
console.log(var1);
}
}
var end = 8;
for (var i = 1; i < end; i++) {
setTimeout(handler(i), 800);
}
答案 3 :(得分:-2)
setTimeout
接受变量作为附加参数:
setTimeout(function(a, b, c) {
console.log(a, b, c);
}, 1000, 'a', 'b', 'c');
编辑:在您的示例中,i
的有效值可能是8
,因为该函数仅在循环结束后被调用。您需要为每次调用传递i
的当前值:
var end=8;
for (var i = 1; i < end; i ++) {
setTimeout(function (i) {
console.log(i);
}, 800, i);
}