我有这个脚本:
for (var i = 1; i <= 2; i++) {
setTimeout(function() { alert(i) }, 100);
}
但是3被提醒两次,而不是1和2。
有没有一种方法传递i,而不把函数写成字符串?
我有这个脚本:
for (var i = 1; i <= 2; i++) {
setTimeout(function() { alert(i) }, 100);
}
但是3被提醒两次,而不是1和2。
有没有一种方法传递i,而不把函数写成字符串?
您必须为每个超时函数安排一个不同的“i”副本。
函数 doSetTimeout(i) { setTimeout(function() { 警报(i); }, 100); } for (var i = 1; i <= 2; ++i) doSetTimeout(i);
如果你不这样做(同样的想法还有其他变体),那么每个计时器处理函数将共享相同的变量“i”。当循环结束时,i的值是多少?这是3 !通过使用中介函数,生成变量值的副本。由于超时处理程序是在该副本的上下文中创建的,因此它有自己的私有“i”可以使用。
编辑:
There have been a couple of comments over time in which some confusion was evident over the fact that setting up a few timeouts causes the handlers to all fire at the same time. It's important to understand that the process of setting up the timer — the calls to setTimeout() — take almost no time at all. That is, telling the system, "Please call this function after 1000 milliseconds" will return almost immediately, as the process of installing the timeout request in the timer queue is very fast. Thus, if a succession of timeout requests is made, as is the case in the code in the OP and in my answer, and the time delay value is the same for each one, then once that amount of time has elapsed all the timer handlers will be called one after another in rapid succession.
If what you need is for the handlers to be called at intervals, you can either use setInterval(), which is called exactly like setTimeout() but which will fire more than once after repeated delays of the requested amount, or instead you can establish the timeouts and multiply the time value by your iteration counter. That is, to modify my example code: function doScaledTimeout(i) { setTimeout(function() { alert(I); }, i * 5000); } (With a 100 millisecond timeout, the effect won't be very obvious, so I bumped the number up to 5000.) The value of i is multiplied by the base delay value, so calling that 5 times in a loop will result in delays of 5 seconds, 10 seconds, 15 seconds, 20 seconds, and 25 seconds.
更新
在2018年,有一个更简单的选择。有了在比函数更窄的作用域中声明变量的新能力,如果这样修改,原始代码将正常工作:
For(令I = 1;I <= 2;我+ +){ setTimeout(函数(){ 警报(我) }, 100); }
与var不同,let声明本身会导致循环的每次迭代都有一个不同的i。
你可以使用立即调用的函数表达式(IIFE)来创建一个围绕setTimeout的闭包:
for (var i = 1; i <= 3; i++) { (函数(索引) { setTimeout(function() { alert(index); }, i * 1000); })(i); }
setTimeout的函数参数在循环变量上关闭。循环在第一个超时之前结束,并显示当前值i,即3。
因为JavaScript变量只有函数作用域,解决方案是将循环变量传递给设置超时的函数。你可以像这样声明和调用这样的函数:
for (var i = 1; i <= 2; i++) {
(function (x) {
setTimeout(function () { alert(x); }, 100);
})(i);
}
答案?
我用它来做一个添加物品到购物车的动画——当点击产品“添加”按钮时,一个购物车图标浮动到购物车区域:
function addCartItem(opts) {
for (var i=0; i<opts.qty; i++) {
setTimeout(function() {
console.log('ADDED ONE!');
}, 1000*i);
}
};
时间单位为单位乘以n周期。
因此,从点击时刻开始,动画开始epoc(每个动画的)是每个一秒单位乘以项目数量的乘积。
epoc: https://en.wikipedia.org/wiki/Epoch_ (reference_date)
希望这能有所帮助!
可以使用setTimeout的额外参数将参数传递给回调函数。
for (var i = 1; i <= 2; i++) { setTimeout(function(j) { alert(j) }, 100, i); }
注意:这在IE9及以下浏览器上不起作用。
好吧,另一个基于科迪的答案但更一般的解决方案是这样的:
function timedAlert(msg, timing){
setTimeout(function(){
alert(msg);
}, timing);
}
function yourFunction(time, counter){
for (var i = 1; i <= counter; i++) {
var msg = i, timing = i * time * 1000; //this is in seconds
timedAlert (msg, timing);
};
}
yourFunction(timeInSeconds, counter); // well here are the values of your choice.
我也遇到过同样的问题这就是我解决的方法。
假设我想要12个间隔为2秒的延迟
function animate(i){
myVar=setTimeout(function(){
alert(i);
if(i==12){
clearTimeout(myVar);
return;
}
animate(i+1)
},2000)
}
var i=1; //i is the start point 1 to 12 that is
animate(i); //1,2,3,4..12 will be alerted with 2 sec delay
这是因为!
超时函数 回调在循环完成后都运行良好。事实上, 作为计时器,即使它是setTimeout(.., 0),所有 这些函数回调在完成后仍然严格运行 这就是为什么有3个被反射了! 这两个函数都有定义 在每个循环迭代中,分别在相同的共享全局上关闭 范围,实际上只有一个I在里面。
解决方案通过使用执行的自我函数(匿名或更好的IIFE)来声明每个迭代的单一作用域,并在其中有一个i的副本,如下所示:
for (var i = 1; i <= 2; i++) {
(function(){
var j = i;
setTimeout(function() { console.log(j) }, 100);
})();
}
更干净的一个
for (var i = 1; i <= 2; i++) {
(function(i){
setTimeout(function() { console.log(i) }, 100);
})(i);
}
在每个迭代中使用IIFE(自执行函数)为每个迭代创建了一个新的作用域 迭代,这给了我们的超时函数回调机会 为每个迭代关闭一个具有变量的新作用域 有正确的每次迭代值供我们访问。
你可以使用bind方法
for (var i = 1, j = 1; i <= 3; i++, j++) {
setTimeout(function() {
alert(this);
}.bind(i), j * 100);
}
真正的解决方案在这里,但是您需要熟悉PHP编程语言。 你必须混合使用PHP和JAVASCRIPT才能达到你的目的。
请注意:
<?php
for($i=1;$i<=3;$i++){
echo "<script language='javascript' >
setTimeout(function(){alert('".$i."');},3000);
</script>";
}
?>
它完全是你想要的,但要小心如何使之间的关系 PHP变量和JAVASCRIPT变量。