这是我的代码。我想要它做的是写0,等待一秒,写1,等待一秒,写2,等待一秒等等。相反它写5 5 5 5 5
for(i = 0; i < 5; i++) {
setTimeout("document.write(i + ' ')", 1000);
}
答案 0 :(得分:8)
1)您将所有超时设置为同时持续1秒。循环不等待超时发生。所以你有5次超时都同时执行。
2)当超时执行时,循环很长,完成后i
变为5.所以一旦执行,它们都会打印“5”
3)document.write()
将somthing写入页面,在它执行的相同位置。即如果你在一段文字的中间有<script>document.write("xyz")</script>
,它会在文本的中间写上“xyz”。但是,超时不一定在页面上的任何位置。它们只存在于代码中。
这是一个尽可能接近你的解决方案:http://jsfiddle.net/rvbtU/1/
var container = document.getElementById("counter");
for(i = 0; i < 5; i++) {
setTimeout("container.innerHTML += '" + i + " ';", 1000 * i);
}
但是,该解决方案使用setTimeout将字符串计算为javascript的能力,这绝不是一个好主意。
以下是使用anymous函数的解决方案:http://jsfiddle.net/YbPVX/1/
var container = document.getElementById("counter");
var writer = function(number) {
return function() { container.innerHTML += String(number) + " "; };
}
for(i = 0; i < 5; i++) {
setTimeout(writer(i), 1000 * i);
}
编辑:忘了保存第二小提琴。哎呦。现在修好了。
答案 1 :(得分:3)
大多数可用的答案都提供了不好的建议。 *具体来说,你不应该再将字符串传递给setTimeout
(它仍然有效,但不鼓励),它不是更长2000
,有更好的方法可以做到这一点。
setTimeout
将函数作为第一个参数,这就是你应该做的,但是在循环中调用setTimeout
时会出现一些问题。
这看起来应该有效:
var i;
for ( i = 0; i < 5; i++ )
{
setTimeout(function(){
document.write( i + ' ' );
}, 1000 * (i + 1) );
}
但事实并非如此。问题是,当setTimeout
执行该函数时,循环将i
增加到5
,因此您将重复相同的值。
有一些修复。如果您愿意冒with
声明,可以尝试以下方法:
var i;
for ( i = 0; i < 5; i++ )
{
with( { i:i } )
{
setTimeout(function(){
document.write( i + ' ' );
}, 1000 * (i+1) );
}
}
请注意,通常不建议使用with
,就像将string
值传递给setTimeout
一样,所以我并不建议这种做法。
更好的方法是使用闭包:
var i;
for ( i = 0; i < 5; i++ )
{
(function(i){
setTimeout(function(){
document.write( i + ' ' );
}, 1000 * (i+1) );
})(i);
}
为了解释发生了什么,匿名函数包装器(function(i){...code...}
)立即执行,因为它包含在parens中并作为值传递i
:
(function(i){...code...})(i);
这会强制i
使用的document.write
变量与for
循环中使用的变量不同。如果差异太混乱,您甚至可以更改匿名函数包装器中使用的参数:
(function(a){document.write(a+' ')})(i);
*当我开始撰写此问题时,有许多答案描述了如何修复字符串以使用setTimeout
,尽管他们技术上工作,他们没有'包括为什么它们可以工作(因为'document.write(“'+ i +'”);'由于字符串连接而在调用时评估i
,而不是评估{{ 1}}在运行时像以前的版本一样),他们肯定没有提到它是调用i
的旧方法。
答案 2 :(得分:2)
试
var i = 1;
function timeout(){
document.write(i + ' ');
i++;
if (i == 5) return;
setTimeout(timeout, 1000);
}
timeout();
答案 3 :(得分:1)
您还可以使用setInterval
和clearInterval
:
var i = 0;
var f = setInterval(function() {
if(i == 4) clearInterval(f);
document.write(++i + ' ');
}, 1000);
我认为这段代码非常易读。
答案 4 :(得分:1)
你有一个clousures的问题,你可以试试这个:
var timeout = function(){
var i = 0;
return function(){
document.write(i+ ' ');
i++;
if(i!==5)
setTimeout(timeout,1000);
};
}();
setTimeout(timeout,1000);
以下是jsBin http://jsbin.com/uloyuc/edit
中的示例答案 5 :(得分:1)
首先,从不将字符串传递给setTimeout。使用功能,它更清洁。
其次,你必须“关闭”循环值。我打赌这就是你想要的。
for(var i = 0; i < 5; i++) {
(function(i) {
setTimeout(function() {
document.write(i + ' ')
}, i * 1000);
}(i));
}
在此处查看有关关闭循环值的自执行函数的更多信息http://www.mennovanslooten.nl/blog/post/62
正因为我喜欢它,这里是CoffeeScript中的等价物,而do
关键字可以帮助解决这个问题。
for i in [0..4]
do (i) ->
setTimeout ->
document.write "#{ i } "
, i * 1000
答案 6 :(得分:1)
你可以尝试这样:
var tick_limit = 5; // Or any number you wish representing the number of ticks
var counter = 0; // Or any number you wish
var timer_interval = 1000; // Interval for the counter
var timer;
function timerTick()
{
if(counter < tick_limit)
{
// Execute code and increase current count
document.body.innerHTML+=(counter + ' '); // Append the counter value to the body of the HTML page
counter++;
timer = setTimeout(timerTick,timer_interval);
}
else
{
// Reset everything
clearTimeout(timer);
counter = 0;
}
}
function startCounter()
{
clearTimeout(timer); // Stop current timer
timer = setTimeout(timerTick,timer_interval); // Start timer with any interval you wish
}
...
// Start timer when required
startCounter();
...
这样,多次调用startCounter将导致单个计时器执行代码
答案 7 :(得分:0)
你同时触发五次超时。
我喜欢Pindatjuh's answer,但这是另一种有趣的方式。
这种方式在前一个超时完成后开始下一个超时:
// Wrap everything in a self executing anonymous function so we don't pollute
// the global namespace.
//
// Note: Always use "var" statments or you will pollute the global namespace!
// For example "for(i = 0; i < 5; i++)" will pollute the global namespace
// unless you have "var i; for(i = 0; i < 5; i++)" or
// "for(var i = 0; i < 5; i++)" & all of that is not in the global namespace.
//
(function() {
// "i" will be available within doThis()
// you could also pass "i" as an argument
var i = 0,
doThis = function() {
// setTimeout can take an anonymous function
// or a regular function. This is better than
// eval-ing a string.
setTimeout(function() {
document.write(i + ' ');
++i;
// Do the function again if necessary
if (i < 5) doThis();
}, 1000);
}
// Let's begin!
doThis();
})();