15

试图解决这个问题时有点头疼。我想要做的是有一个带有参数的自定义 setTimeout ,不必创建一个函数来传递它。让我通过代码来解释:

想要避免:

function makeTimeout(serial){
  serial.close();
}

setTimeout(makeTimeout(sp.name), 250);

我想要做的就是通过以下方式调用 1 班轮:

setTimeout(function(arg1){ .... }(argument_value), 250);

可以这样做还是只能传入无参数函数?

4

4 回答 4

24

您可以向它传递一个匿名函数,该函数makeTimeout使用给定的参数调用:

setTimeout(function () {
  makeTimeout(sp.name);
}, 250);

还有一种替代方法,使用bind

setTimeout(makeTimeout.bind(this, sp.name), 250);

但是,此功能是 ECMAScript 第 5 版功能,尚未在所有主要浏览器中支持。为了兼容性,您可以包含MDN 上提供bindsource,允许您在本机不支持它的浏览器中使用它。

演示

于 2012-09-17T00:27:32.837 回答
7

如果您不想声明单独的函数,可以使用立即调用的函数表达式和闭包,例如

// Parameter to use
var bar = 'bar';

// Function to call
function foo(arg) {
  alert(arg);
}

// Go…
setTimeout(
  (function(arg1){
    return function(){
      foo(arg1);
    };
  }(bar)), 2000);

或者,您可以使用函数构造函数:

setTimeout( Function('foo(bar)'), 2000);

或者你可以使用一个字符串:

setTimeout('foo(bar)', 1000);

这本质上是一回事。现在等待“的嚎叫,但这就像使用 eval,每个人都知道 eval 是邪恶的,并且是一个巨大的安全漏洞——你所有的长子都注定了!

但严重eval的是,(和 Function 构造函数)效率低下并且可能导致惰性编程,因此请使用另一个选项,例如上面的第一个选项。

于 2012-09-17T01:46:43.690 回答
3

似乎该功能已添加到某些浏览器将参数传递给 setTimeout:

语法:( setTimeout (function (p1,p2) {},1000,p1,p2); 添加任意数量的参数)

如果您想确保它在任何地方都能正常工作,您可以使用随附的代码。

注意:如果你想在安装后立即设置超时,最好使用回调参数并在那里进行

例如

installSwizzledTimeout(function(param1,param2){
    setTimeout(myFunc,200,param1,param2);},param1,param2);
}

这是因为它使用一种技巧来检测是否需要它,方法是设置一个非常短的超时并计算参数。

window.swizzledSetTimeout = function (fn, ms) {
    if (arguments.length === 2) {
        //console.log("Bypassing swizzledSetTimeout");
        return window.originalSetTimeout(fn, ms);
    } else {
        var args = [];
        for (i = 2; i < arguments.length; i++) {
            args.push(arguments[i])
        };
        //console.log("Setting swizzledSetTimeout for function (",args,") {...} in ",ms," msec");
        var retval = window.originalSetTimeout(function () {
            //console.log("Invoking swizzledSetTimeout for function (",args,") {...}");
            fn.apply(null, args);
        }, ms);
        return retval;
    }
}

function installSwizzledTimeout(cb) {
    var args = [];
    for (i = 1; i < arguments.length; i++) {
        args.push(arguments[i])
    };
    setTimeout(function (arg) {
        //console.log("arguments.length:",arguments.length,window.setTimeout.toString());
        if (arguments.length == 0) {

            function doInstall() {
                //console.log("Installing new setTimeout");
                window.originalSetTimeout = window.setTimeout;
                window.setTimeout = function setTimeout() {
                    return window.swizzledSetTimeout.apply(null, arguments);
                };
                if (cb) {
                    cb.apply(null, args);
                };
            }

            if (window.setTimeout.toString().indexOf("swizzledSetTimeout") < 0) {
                doInstall();
            }
        } else {
            //console.log("existing set time supports arguments ");
            if (cb) {
                cb.apply(null, args);
            };
        }
    }, 0, 1, 2, 3, 4);
}
于 2014-06-23T08:12:05.640 回答
0

我有一个需要恒定超时设置的方法,该方法还具有最终执行函数的参数,所以我使用匿名函数执行以下操作:

function checkPageLoaded(checker, callback, nextCallTime) {
    return () => {
        let checkoutLoader = document.querySelector(checker);
        if(checkoutLoader === null)
            callback();
        else
            setTimeout(checkPageLoaded(checker, callback, nextCallTime), nextCallTime);
    }
}

然后按如下方式调用它:

setTimeout(checkPageLoaded('.loader', reloadPagination, 500), 500);

这样,使用参数执行的所需函数将是定义为匿名函数的函数。

于 2019-11-20T22:40:22.137 回答