【问题标题】:Function.prototype.bind.apply() doesn't work as expectedFunction.prototype.bind.apply() 不能按预期工作
【发布时间】:2015-06-26 12:08:12
【问题描述】:

我有一个函数 myfunc 并想将 bind 它作为一个特定的 this 参数和 bind 的其他参数作为单个数组,而不是参数列表(因为我将参数列表作为参数函数,执行此代码的位置)。 为此,我在bind 上使用apply,如下所示:

var myfunc = function(arg1, arg2){
    alert("this = " + this + ", arg1 = " + arg1 + ", arg2 = " + arg2);
}
var bindedMyfunc = myfunc.bind.apply("mythis", ["param1", "param2"]);
bindedMufunc();

这导致Uncaught TypeError: Bind must be called on a function

我做错了什么?你能详细解释一下,当我运行这段代码时发生了什么,因为现实似乎与我的看法相矛盾?

答案总结: 似乎bind 本身有自己的this 参数,也就是函数,它被调用了。例如。当你说myfunc.bind(args)时,bindthis就是myfunc

通过在bind 上调用apply,我错误地将bind 的this 分配给了“mythis”,这不是一个函数,并且不能在其上调用bind

所以,解决方案是使用

myfunc.bind.apply(myfunc, ["mythis"].concat(["param1", "param2"]))

另外,如果你想立即调用绑定的 myfunc,你可以说:

myfunc.apply.bind(myfunc)("mythis", ["param1", "param2"])

但这还不够我的情况,因为我需要将绑定函数作为参数传递给addEventListener

谢谢你们的帮助,伙计们!

【问题讨论】:

  • 第一个解决方案是myfunc.bind.apply(myfunc, ["mythis", "param1", "param2"])),您忘记了摘要中的数组字面量。

标签: javascript functional-programming function-binding


【解决方案1】:

您应该将该函数用作apply 方法的第一个参数。使用myfunc.bind并没有将函数与调用关联起来,它具有Function.prototype.bind的效果,你也可以使用它。

bind 方法的第一个参数 (thisArg) 应该是数组中的第一项。

var bindedMyfunc = Function.prototype.bind.apply(myfunc, ["mythis", "param1", "param2"]);

【讨论】:

  • 啊,我想我明白了,多亏了你的例子,出了什么问题。 bind 有自己的this,在这种情况下应该是调用它的函数(myfunc)。因此,我必须将myfunc 作为第一个参数,然后使用concatmythis[param1, param2] 构建参数列表。
【解决方案2】:

似乎 bind 本身有自己的 this 参数,也就是函数,它被调用了。例如。当你说myfunc.bind(args)时,bindthis就是myfunc

没错。如果要应用bind,则必须将其应用到函数(第一个参数),并将bind 参数(包括预期的this 值)作为数组(第二个参数)传递:

(Function.prototype.bind).apply(myfunc, ["mythis", "param1", "param2"])
// which is equivalent to
myfunc.bind("mythis", "param1", "param2")
(…args) => myfunc.call("mythis", "param1", "param2", …args) // ES6 syntax

但是,还有另一种方法可以解决您的问题:将apply 绑定到函数,并部分应用建议的apply 参数:

(Function.prototype.apply).bind(myfunc, "mythis", ["param1", "param2"])
// which is equivalent to
(…args) => myfunc.apply("mythis", ["param1", "param2"], …args) // ES6 syntax

【讨论】:

  • 第二种方法的问题是..args变得没用了,我也在考虑类似(fn.call).bind.apply(call, [fn, "this", params]).apply.bind()的东西,但是遵循所有this的值变得如此复杂,它会更干净写一个包装器
  • 是的,…args 变得毫无用处,但您似乎不想在您的bindedMufunc(); 通话中使用它们?如果您希望bindedMufunc 接收更多参数,则必须使用第一种方法。
  • @PaulS。抱歉,伙计们,昨天对我的问题的编辑引入了一些混乱 - 刚刚成功测试了 outmyfunc.bind.apply(myfunc, ["mythis"].concat(["param1", "param2"])) 解决方案。它工作正常。感谢您的帮助!
  • @Bob:我认为你应该接受 Guffa 的回答
【解决方案3】:

也许你想bind apply 而不是applying bind

var bindedMyfunc = Function.prototype.apply.bind(myfunc);
bindedMyfunc('obj', [1, 2]); // this = obj, arg1 = 1, arg2 = 2

我经常使用这种模式使hasOwnProperty 检查更短而不会被隐藏;

var has = Function.prototype.call.bind(Object.hasOwnProperty);
has({foo:1}, 'foo'); // true
has({foo:1}, 'bar'); // false

【讨论】: