我有一些JavaScript代码,看起来像:

function statechangedPostQuestion()
{
  //alert("statechangedPostQuestion");
  if (xmlhttp.readyState==4)
  {
    var topicId = xmlhttp.responseText;
    setTimeout("postinsql(topicId)",4000);
  }
}

function postinsql(topicId)
{
  //alert(topicId);
}

我得到一个错误,topicId没有定义 在我使用setTimeout()函数之前,一切都在工作。

我希望我的postinsql(topicId)函数在一段时间后被调用。 我该怎么办?


当前回答

David Meister的回答似乎考虑到了在调用setTimeout()之后、匿名函数调用之前可能立即改变的参数。但这太麻烦了,而且不太明显。我发现了一种优雅的方法,可以使用IIFE(立即调用的函数表达式)完成几乎相同的事情。

在下面的示例中,currentList变量被传递给IIFE, IIFE将其保存在闭包中,直到调用延迟函数。即使变量currentList在代码显示后立即改变,setInterval()也会做正确的事情。

如果没有这种IIFE技术,setTimeout()函数肯定会为DOM中的每个h2元素调用,但所有这些调用都只能看到最后一个h2元素的文本值。

<script>
  // Wait for the document to load.
  $(document).ready(function() {
  $("h2").each(function (index) {

    currentList = $(this).text();

    (function (param1, param2) {
        setTimeout(function() {
            $("span").text(param1 + ' : ' + param2 );
        }, param1 * 1000);

    })(index, currentList);
  });
</script>

其他回答

在做了一些研究和测试之后,唯一正确的实现是:

setTimeout(yourFunctionReference, 4000, param1, param2, paramN);

setTimeout将所有额外的参数传递给你的函数,以便在那里处理它们。

匿名函数可以用于非常基本的东西,但在一个对象的实例中,你必须使用“this”,没有办法使它工作。 任何匿名函数都会将“this”更改为指向窗口,因此您将失去对象引用。

setTimeout是WHAT WG定义的DOM的一部分。

https://html.spec.whatwg.org/multipage/timers-and-user-prompts.html

方法为:-

Handle = self。setTimeout(处理程序[,timeout[,参数…]]) 在超时毫秒后安排一个超时运行处理程序。任何 参数直接传递给处理程序。

setTimeout(postinsql, 4000, topicId);

显然,IE10支持额外的参数。或者,您也可以使用setTimeout(postinsql。bind(null, topicId), 4000);,但是传递额外的参数更简单,这是更可取的。

历史事实:在VBScript时代,在JScript中,setTimeout的第三个参数是语言,作为一个字符串,默认为“JScript”,但可以选择使用“VBScript”。https://learn.microsoft.com/en-us/previous-versions/windows/internet-explorer/ie-developer/platform-apis/aa741500 (v % 3 dvs.85)

//Some function, with some arguments, that need to run with arguments var a = function a(b, c, d, e){console.log(b, c, d, e);} //Another function, where setTimeout using for function "a", this have the same arguments var f = function f(b, c, d, e){ setTimeout(a.apply(this, arguments), 100);} f(1,2,3,4); //run //Another function, where setTimeout using for function "a", but some another arguments using, in different order var g = function g(b, c, d, e){ setTimeout(function(d, c, b){a.apply(this, arguments);}, 100, d, c, b);} g(1,2,3,4);

用一个简单的带有两个参数的加法函数来回答这个问题。

var x = 3, y = 4;

setTimeout(function(arg1, arg2) { 
  return () => delayedSum(arg1, arg2);
}(x, y), 1000); 

function delayedSum(param1, param2) {
     alert(param1 + param2); // 7
}

我最近遇到了需要在循环中使用setTimeout的独特情况。理解这一点可以帮助您理解如何将参数传递给setTimeout。

方法1

使用forEach和Object。根据Sukima的建议:

var testObject = {
    prop1: 'test1',
    prop2: 'test2',
    prop3: 'test3'
};

Object.keys(testObject).forEach(function(propertyName, i) {
    setTimeout(function() {
        console.log(testObject[propertyName]);
    }, i * 1000);
});

我推荐这个方法。

方法2

使用绑定:

var i = 0;
for (var propertyName in testObject) {
    setTimeout(function(propertyName) {
        console.log(testObject[propertyName]);
    }.bind(this, propertyName), i++ * 1000);
}

JSFiddle: http://jsfiddle.net/MsBkW/

方法3

或者如果你不能使用forEach或bind,使用IIFE:

var i = 0;
for (var propertyName in testObject) {
    setTimeout((function(propertyName) {
        return function() {
            console.log(testObject[propertyName]);
        };
    })(propertyName), i++ * 1000);
}

方法4

但如果你不关心IE < 10,那么你可以使用Fabio的建议:

var i = 0;
for (var propertyName in testObject) {
    setTimeout(function(propertyName) {
        console.log(testObject[propertyName]);
    }, i++ * 1000, propertyName);
}

方法五(ES6)

使用块作用域变量:

let i = 0;
for (let propertyName in testObject) {
    setTimeout(() => console.log(testObject[propertyName]), i++ * 1000);
}

不过我还是推荐使用Object。在ES6中使用forEach键。