如果我在Javascript中有一个对象,并且它的属性之一是一个函数:
function cow() {
this.timesMooed = 0;
this.sayMoo = function () {
this.timesMooed++;
return "moo";
};
}
说我还有另一个函数,它将某个函数作为参数,调用它并记录结果:
var actionResults = [];
function doAction(action) {
actionResults.push(action());
}
现在让我们将其付诸实践,看看会发生什么:
var jerry = new cow();
doAction(jerry.sayMoo);
console.log(actionResults);
// Outputs ["moo"] -this is correct
console.log(jerry.timesMooed);
// Outputs 0 -uh oh
如何传递函数,以便Jerry
正在运行该函数?
答案 0 :(得分:3)
当您将引用传递给函数doAction
并使用action()
进行调用时,调用上下文将更改,这就是确定this
的值的原因。您需要使用bind
来将this
的值锁定为jerry
:
function cow() {
this.timesMooed = 0;
this.sayMoo = function () {
this.timesMooed++;
return "moo";
}
}
var actionResults = [];
function doAction(action) {
actionResults.push(action());
}
var jerry = new cow();
// use bind, which makes a function with `this` set properly
doAction(jerry.sayMoo.bind(jerry));
console.log(actionResults);
console.log(jerry.timesMooed);
或者,您可以使用箭头功能=>
来按词法绑定this
:
function cow() {
this.timesMooed = 0;
// use arrow function here instead
this.sayMoo = () => {
this.timesMooed++;
return "moo";
}
}
var actionResults = [];
function doAction(action) {
actionResults.push(action());
}
var jerry = new cow();
// no need to bind() now
doAction(jerry.sayMoo);
console.log(actionResults);
console.log(jerry.timesMooed);
答案 1 :(得分:1)
问题是在方法中使用了this
关键字,我们从接收者对象中调用了该方法,而this
未绑定到我们希望它绑定到该对象的对象,即jerry情况。
请注意,当我们需要将特定对象绑定到函数的this
值时,必须显式设置方法和函数中的this
值。
解决方案
解决方案易于使用正确的上下文
即我们希望this
引用jerry,因此在使用jerry对象的sayMoo方法调用doAction方法时,请使用绑定函数调用并将jerry作为此参数传递
doAction(jerry.sayMoo.bind(jerry));
答案 2 :(得分:1)
尝试创建构造函数
class cow {
constructor(){
this.timesMooed = '';
}
sayMoo() {
this.timesMooed+=1;
return "moo";
}
}
var actionResults = [];
function doAction(action) {
actionResults.push(action);
}
var jerry = new cow();
doAction(jerry.sayMoo());
console.log(actionResults);
console.log(jerry.timesMooed);
答案 3 :(得分:0)
正如@Mark_M所说,更好的方法是使用箭头功能,但是此功能迫使您使用ES6而不是ES5,因为bound function是ES5中引入的。 另一种方法是利用可变范围的好处,例如:
function cow() {
this.timesMooed = 0;
var that = this;
this.sayMoo = function (){
that.timesMooed++;
return "moo";
}
}
...