为什么 setTimeout 不等待调用函数?

Why doesn't setTimeout wait to call a function?

我想创建一个简单的游戏。我试图在几秒钟后递归地复制 div 。复制后,它会创建具有新的唯一 ID (ID+i) 的新 div。

想法是,它会不断创建 div,用户必须在达到最大值(游戏结束)之前尽可能长时间地点击它们以将其删除。

它不会正确地等待创建 divs。我想每隔几秒从现有的 div 中创建新的 divs,但它要么在我 运行 时立即创建所有 15 个,要么只创建 1 个并停在那里。

JSFIDDLE - https://jsfiddle.net/namelesshonor/msrkxq63/

function spawnFly() {
if(x >= 15){
    alert("YOU LOST\n15 Flys have infested your screen!");
}
else if(x < 15) {   
    x++; // adds another fly to the counter 
    setTimeout(duplicate(), 2000); // spawns a new fly after a few secs
    animateDiv(); // animate the spawned fly
    spawnFly(); // called recursively until fly count is met
}   
};

function duplicate() {
var original = document.getElementById('fly'+i);
var clone = original.cloneNode(true);
clone.id = "fly" + i++;
clone.onclick = swat;
original.parentNode.appendChild(clone);
};

function animateDiv(){
var newq = makeNewPosition();
var oldq = $('.shoo').offset();
var speed = calcSpeed([oldq.top, oldq.left], newq);
$('.shoo').animate({ top: newq[0], left: newq[1] }, speed, function(){
  animateDiv();        
});
};

setTimeout的参数应该是指向duplicate的函数指针,而不是调用duplicate函数的结果。

setTimeout(duplicate(), 2000);

应该是

setTimeout(duplicate, 2000);

此外,您可能打算在超时时调用 spawnFly 函数,而不是重复函数。然后将立即调用复制函数以 "spawn" 一只新苍蝇。然后在 2 秒内,spawnFly 函数被调用到 duplicate 另一只 fly 并再次排队 spawnFly。按照您目前的设置方式,它会立即返回到 spawnFly 函数中,在 2 秒内排队等待 15 只苍蝇产卵,并立即达到飞行计数 (x)

此外,您的 i 增量会导致 off by 1 错误,因此您总是试图将下一次飞行的值分配给 original。您应该使用预增量 (++i) 而不是 post-增量 (i++) 来获得您想要的结果

应用所有更改: https://jsfiddle.net/msrkxq63/3/

当您在您的示例中调用 setTimeout 时,您传递的是 duplicate() 的结果,而不是函数 duplicate 本身作为回调。由于 duplicate 没有 return 任何东西,setTimeout 尝试调用函数 undefined。您可以这样称呼它(作为匿名回调):

setTimeout(function() { duplicate }, 2000)

或者简单地说,

setTimeout(duplicate, 2000)

如果您注意到 setTimeout(duplicate(),2000); 中的 duplicate()
这是一个函数调用。
setTimeout 的第一个参数是一个函数。 如果您通过 duplicate(),
它在等待之前得到评估并查找 return 值并调用它。
功能与否,它在 函数调用后等待,并在
等待后什么也不做。 所以我们可以说流程是:
1 .回调 = duplicate()duplicate 在等待之前调用) = 而不是函数 duplicate 本身。
2。毫秒 = 2000
3。 2 秒后调用 return 值。
正确的代码是:
setTimeout(duplicate,2000)//Note that there are no brackets here