何时在JS中使用.bind()

时间:2014-10-21 00:45:24

标签: javascript

有大量关于如何使用bind()的博客和帖子以及它与call()apply()有何不同,但为什么我应该使用bind()

我发现很多给出的例子非常罕见,例如:

"use strict";

function Person(firstName, lastName){
  this.firstName = firstName
  this.lastName = lastName
}

Person.prototype.say = function(message){
  return '[' + this + ']: ' + this.firstName + ' ' + this.lastName + ' said: "' + message + '"'
}

Person.prototype.toString = function(){
  return '[Person]'
}

moe = new Person("Mo", "El")


func = moe.say.bind(moe)

console.log(func("asdasda"))

我不知道什么时候我想让函数等于某个其他变量并使用该变量而不是原始函数,更不用说该变量等于{的实例的绑定{1}}对象。

有什么好的例子吗?

3 个答案:

答案 0 :(得分:7)

简而言之,.bind()返回一个新函数,该函数在调用时将调用具有特定this值的原始函数,并且(可选)将某些新参数预先填充到参数列表中。

当您需要传递回调(例如某种函数引用)时,会使用

.bind(),但您希望调用者使用特定的this值调用您的函数。当您的函数实际上是一个方法并且您希望将this值设置为特定对象时,这是最常见的,因此该方法将对该特定对象进行操作。如果您在这些情况下不使用.bind(),那么this值将由来电者(而不是您)确定,如果来电者没有专门设置,则会{最终成为全局对象或(在严格模式下)undefined。如果您传递的是一个依赖于this特定值的方法来完成其工作,那么它将无法正确使用错误的this值。

因此,如果要在调用回调时控制this的值,可以使用.bind()。在内部,.bind()只创建一个小的存根函数,只记住传递它的this值并使用.apply()调用函数来设置this值。 .bind()并不神奇,因为它也可以手动完成。

.bind()还具有向函数添加额外参数的功能,因此,如果要添加超出回调正常调用者的参数,您也可以指定具有.bind()的参数。它创建一个存根函数,它将添加这些额外的参数并设置this值。


我们假设您拥有Person个对象,并希望将按钮挂钩到特定.say()对象的Person方法。

<button id="talk">Talk</button>

而且,如果你试过这个javascript:

"use strict";
var bob = new Person("Bob", "Smith");
document.getElementById("talk").addEventListener("click", bob.say);

你会发现调用say()方法,但它会遗漏两件事。它将缺少正确的this引用(将被设置为button对象,因为它是addEventListener调用其回调的方式)并且它将缺少say(message)的参数预计。

所以,您可以使用自己的存根函数自行解决这个问题,该函数使用所有正确的参数调用bob.say()

"use strict";
var bob = new Person("Bob", "Smith");
document.getElementById("talk").addEventListener("click", function(e) {
    bob.say("Hello");
});

或者,您可以使用.bind()

"use strict";
var bob = new Person("Bob", "Smith");
document.getElementById("talk").addEventListener("click", bob.say.bind(bob, "Hello"));

.bind()中没有魔法。它可以在javascript中完全模拟。事实上,这是来自MDN的polyfill:

if (!Function.prototype.bind) {
  Function.prototype.bind = function(oThis) {
    if (typeof this !== 'function') {
      // closest thing possible to the ECMAScript 5
      // internal IsCallable function
      throw new TypeError('Function.prototype.bind - what is trying to be bound is not callable');
    }

    var aArgs   = Array.prototype.slice.call(arguments, 1),
        fToBind = this,
        fNOP    = function() {},
        fBound  = function() {
          return fToBind.apply(this instanceof fNOP && oThis
                 ? this
                 : oThis,
                 aArgs.concat(Array.prototype.slice.call(arguments)));
        };

    fNOP.prototype = this.prototype;
    fBound.prototype = new fNOP();

    return fBound;
  };
}

由于所有错误检查,这可能看起来比它更复杂,但它实际上只是返回一个组合了两组参数的新函数,然后使用特定的this调用原始函数值。

答案 1 :(得分:1)

如果您想要一个始终以特定bind()值运行的函数,请使用this

当将函数作为回调或事件处理程序传递时,它对更多函数式编程很有用。

var User = function(name) { this.name = name; };
User.prototype.poke = function() { alert "Hey, don't poke " + this.name; };
var bob = User('Bob');

// assume jQuery for brevity, and because it screws with `this` in callbacks
$('#some-element').click(bob.poke.bind(bob));

这会警告&#34;嘿,不要捅Bob&#34;因为你传递了一个绑定函数。因此,如果该元素明确是关于Bob的,那么将事件处理程序绑定到他是有意义的。


但是,如果没有bind,还有其他方法可以做到这一点。

$('#some-element').click(function() {
  bob.poke();
});

差异可能是风格问题。并且bind并没有在所有浏览器中获得大量支持,所以很多JS程序员都想出了其他方法,而且很多其他方法在今天仍在使用。


一个清除胜利是指您希望将相同的函数传递到许多不同的地方,并且您希望明确设置this

var bobPoke = bob.poke.bind(bob);

onFoo(bobPoke);
onBar(bobPoke);
onBaz(bobPoke);

答案 2 :(得分:1)

这可能是在实际意义上解释它的最简单方法。由于大多数答案都给出了理论上的定义和解释,因此我将展示一个简单的用例。如果希望被调用的函数具有与默认值不同的值,则可以使用bind

var NS = {
  user     : "self",
  getUser  : function() { return this.user; }
};

var CLOSURE = NS.getUser;

// error user is undefined, "this" in that context refers to the global object, "window"
console.log(CLOSURE());

// Bind the function call to NS object
console.log(CLOSURE.bind(NS)());

http://jsfiddle.net/ev3z3td3/2/