有没有办法创建一个绑定函数,在数组中提供它的参数?

时间:2014-05-18 11:19:42

标签: javascript

假设我有以下功能。

var func = function(a, b, c) {
    console.log(a);
    console.log(b);
    console.log(c);
}

我想要做的是通过在数组中提供它的参数来调用它:

func.apply(null, [1, 2, 3]);

按预期工作。现在,如果我想要异步调用该函数,例如使用setTimeout,我该怎么做?我尝试了以下方法:

setTimeout(func.bind.apply(null, [null, 1, 2, 3]), 1000);

但它给了我一个错误:

  

TypeError:必须在函数上调用Bind

有优雅的方法吗?

4 个答案:

答案 0 :(得分:3)

有很多方法可以做到这一点。

方法1:setTimeout额外参数

您是否知道可以像setTimeout那样传递call个额外参数?

setTimeout(func, 1000, 1, 2, 3);

但是假设你有一个参数数组:

setTimeout(func, 1000, [1, 2, 3]); // This will not work

所以你需要做以下事情:

setTimeout(function (args) {
    return func.apply(this, args);
}, 1000, [1, 2, 3]);

不幸的是,这在旧版本的Internet Explorer中无法使用。但是你可以随时这样做:

function applyAsync(f, ms, args) {
    return setTimeout(function () {
        return f.apply(this, args);
    }, ms);
}

您可以按如下方式调用它:

applyAsync(func, 1000, [1, 2, 3]);

在我看来,这是最干净,最快的解决方案。但是,如果你想要一个更聪明的解决方案,那么:

方法2:bindablecallableappliable

我在JavaScript中最喜欢的功能:

var bind = Function.prototype.bind;
var call = Function.prototype.call;
var apply = Function.prototype.apply;

var bindable = bind.bind(bind);
var callable = bindable(call);
var appliable = bindable(apply);

我不会详细解释它是如何运作的,但这是你需要知道的:

  1. bindable函数接受函数f并返回等效于f.bind的函数; f.bind部分适用于任何其他参数。
  2. callable函数接受函数f并返回等效于f.call的函数; f.call部分适用于任何其他参数。
  3. appliable函数接受函数f并返回等效于f.apply的函数; f.apply部分适用于任何其他参数。
  4. 您正在寻找的功能是appliable

    setTimeout(appliable(func, null, [1, 2, 3]), 1000);
    

    这样聪明而优雅。

答案 1 :(得分:2)

你要么

Function.apply.bind(func, null, [1, 2, 3])

Function.bind.apply(func, [null, 1, 2, 3])

目前,您正在bind上应用null,而不是func,这会引发错误。

您可以使用.apply.bind,而不是访问Function上的Function.prototype / func

答案 2 :(得分:1)

您可以将参数传递给Function.prototype.bind本身,就像这样

setTimeout(func.bind(null, 1, 2, 3), 1000);

Online Demo

你得到的错误是因为bind只能对一个函数对象起作用,所以apply的第一个参数应该是实际的函数对象,就像这样

setTimeout(func.bind.apply(func, [null, 1, 2, 3]), 1000);

答案 3 :(得分:1)

您可以通过这种方式应用Function.prototype.bind,它只需要您将null传递给数组的第一个元素,您应该没问题。

var myFun = function (a,b,c) {
    console.log(a,b,c);
}, myFunBound;

myFunBound = Function.prototype.bind.apply(myFun, [null, 1,2,3]);

setTimeout(myFunBound, 1000);