为什么在使用promise的时候,这个在类方法中是未定义的?

我有一个JavaScript类,每个方法返回一个Q诺。 我想知道为什么this是未定义在method2method3 。 有没有更正确的方法来编写这段代码?

 function MyClass(opts){ this.options = opts; return this.method1() .then(this.method2) .then(this.method3); } MyClass.prototype.method1 = function(){ // ...q stuff... console.log(this.options); // logs "opts" object return deferred.promise; }; MyClass.prototype.method2 = function(method1resolve){ // ...q stuff... console.log(this); // logs undefined return deferred.promise; }; MyClass.prototype.method3 = function(method2resolve){ // ...q stuff... console.log(this); // logs undefined return deferred.promise; }; 

我可以通过使用bind来解决这个问题:

 function MyClass(opts){ this.options = opts; return this.method1() .then(this.method2.bind(this)) .then(this.method3.bind(this)); } 

但不完全确定为什么bind是必要的; 是.then()杀了this

this总是调用方法的对象。 但是,将方法传递给then() ,则不会调用它! 该方法将被存储在某处并在稍后被调用。 如果你想保留this ,你将不得不这样做:

 .then(() => this.method2()) 

或者如果你必须这样做的前ES6的方式,你需要保持this之前:

 var that = this; // ... .then(function() { that.method2() }) 

Promise处理程序默认在全局对象( window )的上下文中调用。 在严格模式下( use strict; )时,上下文是undefined 。 这是method2method3发生的事情。

 ;(function(){ 'use strict' Promise.resolve('foo').then(function(){console.log(this)}); // undefined }()); ;(function(){ Promise.resolve('foo').then(function(){console.log(this)}); // window }()); 

对于方法1,您调用方法1 this.method1() 。 这种调用它的方式在this对象的上下文中调用它,这是你的实例。 这就是为什么method1的上下文是实例。

基本上,你传递一个没有上下文引用的函数引用。 this背景是以几种方式确定的:

  1. 隐。 在没有绑定的情况下调用一个全局函数或一个函数假设一个全局上下文。*
  2. 通过直接引用。 如果你调用myObj.f()那么myObj就是this上下文。
  3. 手动绑定。 这是你的一类函数,如.bind.apply 。 这些你明确地陈述this上下文是什么。 这些总是优先于前两个。

在你的例子中,你传递了一个函数引用,所以在它的调用中,它暗示着是一个全局函数或者没有上下文的函数。 使用.bind通过在明确设置的地方创build一个新的函数来解决这个问题。

*这只在非严格模式下才是正确的。 在严格模式下, this被设置为undefined

**假设你正在使用的function没有被手动绑定。

一种方法函数获取它们的上下文( this )来自它们被调用的对象(这就是为什么method1具有正确的上下文 – 它被调用)。 然后你传递一个函数本身的引用。 你可以想象,那么实现看起来像这样:

 function then( callback ) { // assume 'value' is the recently-fulfilled promise value callback(value); } 

在这个例子中, callback是对你的函数的引用。 它没有任何上下文。 正如你已经注意到的,你可以通过绑定函数到上下文,然后再传递给它。