何时在JS中使用.bind()
When to use .bind() in JS
有很多关于如何使用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"))
我不知道什么时候我想让一个函数等于其他变量,并使用该变量而不是原始函数,更不用说该变量等于Person
对象实例的绑定了。
有什么好的例子吗?
简而言之,.bind()
返回一个新函数,当被调用时,该函数将调用具有特定this
值的原始函数,以及(可选)一些预存到参数列表中的新参数。
当您需要传递回调(例如某种函数引用),但您希望调用方使用特定的this
值调用您的函数时,会使用.bind()
。当您的函数实际上是一个方法,并且您希望this
值集是一个特定对象时,这种情况最为常见,因此该方法将对该特定对象进行操作。如果在这些情况下不使用.bind()
,那么this
的值将由调用者(而不是您)确定,如果调用者没有具体设置,它最终将成为全局对象或(在严格模式下)undefined
。如果您传递的方法依赖于this
的特定值来完成其工作,那么它将无法使用错误的this
值正常工作。
因此,如果您想在调用回调时控制this
的值,可以使用.bind()
。在内部,.bind()
只创建一个小的存根函数,它只记住您传递的this
值,并用.apply()
调用您的函数来设置this
值。.bind()
并不神奇,因为它也可以手动完成。
.bind()
还可以向函数添加额外的参数,因此,如果您想添加超出回调的正常调用方使用的参数,也可以使用.bind()
指定这些参数。它创建了一个存根函数,该函数将添加这些额外的参数并设置this
值。
假设您有一个Person
对象,并且想要将一个按钮挂接到特定Person
对象的.say()
方法。
<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
值调用原始函数。
这可能是从实际意义上解释它的最简单方法。由于大多数答案都给出了理论定义和解释,我将展示一个简单的用例。当您希望被调用的函数具有与默认值不同的this值时,可以使用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/
如果希望函数始终以特定的this
值运行,请使用bind()
。
当将函数作为回调或事件处理程序传递时,它对于更多的函数编程非常有用。
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));
这会提醒"嘿,不要戳Bob",因为你给它传递了一个绑定函数。因此,如果该元素明确地与Bob有关,那么将事件处理程序绑定到Bob是有意义的。
当然,在没有bind
的情况下,还有其他方法可以做到这一点。
$('#some-element').click(function() {
bob.poke();
});
差异可能是风格的问题。bind
过去并不是在所有浏览器中都有很多支持,所以很多JS程序员想出了其他方法来实现这一点,而且很多其他方法至今仍在使用。
当您想要将相同的函数传递到许多不同的地方,并且想要显式设置的this
时,clear的一个优点是。
var bobPoke = bob.poke.bind(bob);
onFoo(bobPoke);
onBar(bobPoke);
onBaz(bobPoke);
- Vue.js-插值错误-如何将样式修改为v-bind:style
- 如何防止bind在使用async.series时更改node.js中的原始对象
- Angular ng-bind-html - 阻止执行JS代码
- 尝试在node.js上模拟function.bind()
- Angular.js:如何使用ng-bind来显示concat.数组的元素作为字符串
- ng-bind-html and highlight.js
- 何时在JS中使用.bind()
- 在BIND之后调用JS函数
- Angular.js取消bind()事件中的$http请求
- 在javascript或node.js中是否有等价的std::bind ?
- 新增元素使用delegate() won't bind jscolor.js
- 使用这个/bind的JS原型作用域
- 在JS中是否有任何方法来'bind'一个变量状态的函数
- Ember js将id传递给bind-attr
- 无法读取property 'bind'的定义.React.js
- Less.js + IE8 =对象不支持属性和方法'bind'
- 在backbone.js中使用bind传递上下文
- 在Ember.js中创建模板的Bind函数
- 不能通过.bind (JS)传递数据
- knockout js data-bind child in object