以下代码成功打印出“ foo”。
var obj = {
name: 'foo',
printName: function printName() {
console.log(this.name);
}
};
var printButton= document.getElementById('printIt');
printButton.addEventListener('click', function(){
obj.printName();
});
但是,以下内容不是:
printButton.addEventListener('click', obj.printName() );
我知道解决方案...只需使用
bind
,以便我们引用obj
对象。即:printButton.addEventListener('click', obj.printName.bind(obj) );
为什么然后在第一个示例中不需要使用
bind
呢?我不知道为什么在匿名函数中包装obj.printName()
函数调用会导致console.log
正确引用和正确打印this
,但是当直接在click
之后调用时,您需要使用bind
最佳答案
好了,我在这个问题上评论了一些很好的信息,所以我不妨回答!
功能是一流的
好的,让我们从与其他编程语言非常不同的javascript基础开始:在javascript函数中,一等公民是一流的公民-这只是一种说法,可以将函数保存到变量中,也可以将函数传递给其他函数功能。
const myFunction = function () { return 'whoa a function'; }
array.map(function () { return x + 1; });
并且由于这个奇妙的功能,表达式之间有很大的区别:
表达式1
obj.printName
和
表达式2
obj.printName();
在表达式1中:该函数没有被调用,所以表达式的值是
function
类型在表达式2中:该函数正在被调用,因此表达式的值就是该函数返回的值。就您而言,这是
undefined
addEventListener
方法
addEventListener
带有两个参数:事件类型的
string
事件触发时将运行的
function
。下车,那是什么意思?
您打电话的时候
// doesn't work
printButton.addEventListener('click', obj.printName() );
您没有将类型
function
的值传递给addEventListener
方法,实际上是在传递undefined
。// works
printButton.addEventListener('click', obj.printName.bind(obj) );
然后起作用(由于一个原因),因为第二个参数实际上是
function
类型。bind
是做什么的?为什么返回一个函数?现在我们需要讨论
bind
的实际作用。它与指针* this
有关。*通过指针,我的意思是指向某个对象的引用标识符
bind
是存在于每个函数对象上的一种方法,该方法仅将所需对象的this
指针绑定到函数最好通过一个示例来说明:
假设您有一个具有方法
Fruit
的类printName
。现在我们知道您可以将方法保存到变量中,让我们尝试一下。在下面的示例中,我们分配了两件事:使用
boundMethod
的bind
没有使用
unboundMethod
的bind
class Fruit {
constructor() {
this.name = 'apple';
}
printName() {
console.log(this.name);
}
}
const myFruit = new Fruit();
// take the method `printName`
const boundMethod = myFruit.printName.bind(myFruit);
const unboundMethod = myFruit.printName;
boundMethod(); // works
unboundMethod(); // doesn't work
那么,当您不拨打
bind
时会发生什么呢?为什么不起作用?如果在这种情况下不调用绑定,则可以将存储在标识符
unboundMethod
中的函数的值视为:// doens't work
const unboundMethod = function() {
console.log(this.name);
}
其中函数的内容与
printName
类中的方法Fruit
的内容相同。您知道为什么这是一个问题吗?因为
this
指针仍然存在,但是原本打算引用的对象不在范围内。尝试调用unboundMethod
时,会出现错误,因为它在name
中找不到this
。那么当您使用
bind
时会发生什么呢?松散地将
bind
视为将函数的this
值替换为要传递给bind
的对象。因此,如果我将
myFruit.printName.bind(myFruit)
分配给boundMethod
,则可以想到这样的分配:// works
const boundMethod = function() {
console.log(myFruit.name);
}
其中
this
被替换为myFruit
底线/ TL; DR
何时在事件处理程序中使用
bind
要将函数内的
Function.prototype.bind
替换为另一个对象/指针时,需要使用this
。如果您的函数从不使用this
,则无需使用bind
。那么为什么在第一个示例中我们不需要使用bind?
如果您不需要“采用方法”(即采用
function
类型的值),那么您也不需要使用bind
另一种写法是:如果您直接调用方法从对象中,您不需要bind
相同的对象。在包装函数中,您将直接调用对象的方法(如表达式2中所示)。因为您在调用方法时没有“采用方法”(在“水果”示例中将方法“放入”变量中),所以不需要使用
bind
。printButton.addEventListener('click', function(){
// directly invoke the function
// no method "taking" here
obj.printName();
});
希望这会有所帮助:D
关于javascript - 对于何时在事件处理程序中使用`bind`感到困惑,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43829225/