在原型回调期间上下文丢失

时间:2014-01-15 00:12:06

标签: javascript this

我有一个简单的构造函数,它有firstname和lastname。

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;
}

为了证明这一点,我也附上了jsfiddle

所以我的问题是每当我在getFullName函数this上传递回调时,会以某种方式丢失父对象的上下文(在我们的例子中为johny)并返回为undefined undefinedthis但是,getFullName函数可以正常工作。

我知道this指向window对象而不是回调中的Parent,但我似乎无法找到其背后的原因。

3 个答案:

答案 0 :(得分:1)

jsFiddle Demo

原因是当你传入函数指针johny.flipName时,它是一个匿名函数。您可以通过将其记录到控制台来查看。因此,该函数将在全局(window)范围内执行。

要解决此问题,您必须(如果您愿意)保留回调的范围。您可以使用 callMDN

执行此操作
Parent.prototype.getFullName = function (callback) {
// used alert for the sake of simplicity
 alert("Callback: " + callback.call(this));
 return this.firstName + ' ' + this.lastName;
};

答案 1 :(得分:0)

没有足够的声誉来添加评论,所以这是另一个答案。特拉维斯对于提出问题的方式是正确的。但是,我认为,实际的用例可能有点复杂。如果你使用

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)时;当你可能期待“Bravo Sue”时,你实际上会得到“Bravo Johny”。

我不知道这是不是最佳做法,但我会做的是:

alert("FullName: " + johny.getFullName(function() {
    return sue.flipName();
}));

答案 2 :(得分:0)

在全局代码中, this 始终引用全局对象。在功能代码中, this 的值由函数的调用方式设置(例如直接调用,作为一种方法,使用 new 调用 apply bind )。

如果您希望回调中的具有特定值,请使用callapply在通话中进行设置,例如

callback.apply(this, args);

如果未设置 this 的值,则默认为全局对象(浏览器中的窗口),或者在严格模式下,它将是未定义的。