Javascript 原型中回调期间上下文丢失
我有一个简单的构造函数,它有firstname和lastnameJavascript 原型中回调期间上下文丢失,javascript,this,Javascript,This,我有一个简单的构造函数,它有firstname和lastname function Parent(){ this.firstName; this.lastName; } 该构造函数的原型中定义了四个函数,它们执行自己的任务 Parent.prototype.flipName = function () { return this.lastName + ' ' + this.firstName; } Parent.prototype.setFirstName = fun
function Parent(){
this.firstName;
this.lastName;
}
该构造函数的原型中定义了四个函数,它们执行自己的任务
Parent.prototype.flipName = function () {
return this.lastName + ' ' + this.firstName;
}
Parent.prototype.setFirstName = function (name) {
this.firstName = name;
}
Parent.prototype.setLastName = function (last) {
this.lastName = last;
}
Parent.prototype.getFullName = function (callback) {
// used alert for the sake of simplicity
alert("Callback: " + callback());
return this.firstName + ' ' + this.lastName;
}
为了证明这一点,我也附上了
因此,我的问题是,每当我在getFullName函数上传递callback时,这个会以某种方式丢失父对象的上下文(在我们的例子中是johny),并返回为undefined
但是,此
在getFullName
函数上运行良好
我知道这个
指向的是窗口
对象,而不是回调中的父对象
,但我似乎找不到它背后的原因。
Parent.prototype.getFullName = function (callback) {
// used alert for the sake of simplicity
alert("Callback: " + callback.call(this));
return this.firstName + ' ' + this.lastName;
};
原因是当您传入函数指针johny.flipName时,它是一个匿名函数。您可以通过将其记录到控制台来查看这一点。因此,函数将在全局(窗口
)范围内执行
要解决这个问题,必须(如果愿意)保留回调的范围。您可以使用
Parent.prototype.getFullName = function (callback) {
// used alert for the sake of simplicity
alert("Callback: " + callback.call(this));
return this.firstName + ' ' + this.lastName;
};
没有足够的声誉来添加评论,所以这里是另一个答案。特拉维斯对这个问题的提问方式是正确的。然而,我认为实际用例可能要复杂一些。如果你使用
callback.call(this);
将使用“this”值执行回调函数,该值引用调用getFullName的对象。当您在回调函数中时,这可能是您希望“This”所指的内容,也可能不是。以下面的例子为例
function Parent() {
var self = this;
self.firstName;
self.lastName;
}
function Child() {
var self = this;
self.firstName;
}
Child.prototype.getName = function() {
return this.firstName;
}
Parent.prototype.getFullName = function (callback) {
// used alert for the sake of simplicity
alert("Callback: " + callback.call(this));
return this.firstName + ' ' + this.lastName;
}
Parent.prototype.flipName = function () {
return this.lastName + ' ' + this.firstName;
}
Parent.prototype.setFirstName = function (name) {
this.firstName = name;
}
Parent.prototype.setLastName = function (last) {
this.lastName = last;
}
var johny = new Parent();
johny.setFirstName("Johny");
johny.setLastName("Bravo");
var sue = new Parent();
sue.setFirstName("Sue");
sue.setLastName("Bravo");
// used alert for the sake of simplicity
alert("FullName: " + johny.getFullName(sue.flipName));
当您执行callback.call(this)时;当你可能期待着“布拉沃·苏”的时候,你实际上会得到“布拉沃·约翰尼”
我不知道这是否是最佳实践,但我会做的是:
alert("FullName: " + johny.getFullName(function() {
return sue.flipName();
}));
在全局代码中,它始终引用全局对象。在函数代码中,该值由函数的调用方式设置(例如,直接调用,作为一种方法,使用new、call、apply或bind)
如果希望回调中的该值具有特定值,则在调用中使用或设置它,例如
如果未设置此值,它将默认为全局对象(浏览器中的窗口),或者在严格模式下,它将是未定义的。请参阅不确定发生此情况的原因,但如果替换警报(“回调:“+Callback()”);带有警报(“回调:+Callback.apply(this));“我知道这是指向回调中的窗口对象,而不是父对象,但我似乎找不到它背后的原因。”因为如果以“正常方式”调用函数,即
func()
,则此
引用全局对象(或在严格模式下未定义的
)。有关更多信息,请参阅。这不是“上下文”,而是由调用函数的方式或使用设置的属性。如果不传递,通常应使用call
,而不是apply
arguments@megawac-为什么?没有比这更简单的理由了,更快的操作速度,在内存中减少一个字节的成本typing@megawac-我将给出1字节。更快?我的测试没有结果(但似乎倾向于打电话)。请参阅我的编辑。OP的问题与“匿名”函数(即函数表达式)或作用域无关。函数的作用域完全由调用函数的方式或使用绑定来设置。这与作用域无关。它本质上是一个局部变量,在非严格模式下引用对象,或在严格模式下引用任何值。