不要使用字符串超时。它是有效的eval,这是一件坏事。它之所以有效,是因为它将currentaudio.id 和noteTime 转换为它们自己的字符串表示形式并将其隐藏在代码中。这只有在这些值具有 toString()s 并生成将重新创建值的 JavaScript 文字语法时才有效,这对于 Number 是正确的,但对于其他情况则不然。
setTimeout(playNote(currentaudio.id, noteTime), delay);
这是一个函数调用。 playNote 被立即调用并且函数的返回结果(可能是undefined)被传递给setTimeout(),而不是你想要的。
正如其他答案所提到的,您可以使用带有闭包的内联函数表达式来引用 currentaudio 和 noteTime:
setTimeout(function() {
playNote(currentaudio.id, noteTime);
}, delay);
但是,如果你在一个循环中,并且 currentaudio 或 noteTime 在循环中每次都不同,你就会遇到闭环问题:每次超时都会引用同一个变量,所以当它们'被调用时,您每次都会得到相同的值,即循环早些时候完成时留在变量中的值。
您可以使用 另一个 闭包来解决这个问题,为循环的每次迭代获取变量值的副本:
setTimeout(function() {
return function(currentaudio, noteTime) {
playNote(currentaudio.id, noteTime);
};
}(currentaudio, noteTime), delay);
但这现在有点难看。更好的是Function#bind,它将为您部分应用功能:
setTimeout(playNote.bind(window, currentaudio.id, noteTime), delay);
(window用于在函数内部设置this的值,这里不需要bind()的特性。)
但是,这是 ECMAScript 第五版功能,并非所有浏览器都支持。因此,如果您想使用它,您必须首先获得支持,例如:
// Make ECMA262-5 Function#bind work on older browsers
//
if (!('bind' in Function.prototype)) {
Function.prototype.bind= function(owner) {
var that= this;
if (arguments.length<=1) {
return function() {
return that.apply(owner, arguments);
};
} else {
var args= Array.prototype.slice.call(arguments, 1);
return function() {
return that.apply(owner, arguments.length===0? args : args.concat(Array.prototype.slice.call(arguments)));
};
}
};
}