ES6 / Bluebird Promises的对象方法

12

我正在Windows上使用带有harmony标志的node v0.11.14-nightly-20140819-pre

我的JavaScript对象具有在其原型中定义的两种方法:

function User (args) {
    this.service= new Service(args);
}

User.prototype.method2 = function (response) {
    console.log(this); // <= UNDEFINED!!!!
};

User.prototype.method1 = function () {
    .............
    this.service.serviceMethod(args)
        .then(this.method2)
        .catch(onRejected);
};

function onRejected(val) {
    console.log(val);
}
Service 对象的 serviceMethod 方法返回一个 Promise。

当我像下面这样使用 User 对象:

let user = new User(args);
user.method1();

then方法在Promise对象被解决后调用User对象的method2方法时,this变为undefined。我尝试了ES6和Bluebird两种Promise实现方式。

为什么在这种情况下this会变成undefined呢?

2个回答

15

为什么在这种情况下this最终成为undefined

因为你传递了一个函数,而不是绑定到实例的方法。这个问题甚至不是特定于Promise的,参见如何在回调函数中访问正确的`this`上下文?以获取通用解决方案:

….then(this.method2.bind(this))… // ES5 .bind() Function method

….then((r) => this.method2(r))… // ES6 arrow function

然而,Bluebird提供了另一种将函数作为方法调用的方式:

this.service.serviceMethod(args)
    .bind(this)
    .then(this.method2)
    .catch(onRejected);

6

需要说明的是,这是一个通用的Javascript问题,也可以使用纯Javascript特性来解决。例如,你也可以这样做:

User.prototype.method1 = function () {
    .............
    this.service.serviceMethod(args)
        .then(this.method2.bind(this))
        .catch(onRejected);
};

这里使用了内置于JavaScript中的Function.prototype.bind(),并且每个函数都具备这个功能。它会创建一个函数存根(即传递给.then()的内容),该存根将在调用method2()之前自动重新附加所需的this值。

1
这就是我最终采取的做法,以保持与ES6 Promise的兼容性。 - krl
我最终采用了这个解决方案,并在需要单独的原型方法过于冗长时使用了“fat arrow”语法。我相信两者都是ES6+兼容的。 - Tom

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接