为什么在使用promise的时候,这个在类方法中是未定义的?
我有一个JavaScript类,每个方法返回一个Q
诺。 我想知道为什么this
是未定义在method2
和method3
。 有没有更正确的方法来编写这段代码?
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
。 这是method2
和method3
发生的事情。
;(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
背景是以几种方式确定的:
- 隐。 在没有绑定的情况下调用一个全局函数或一个函数假设一个全局上下文。*
- 通过直接引用。 如果你调用
myObj.f()
那么myObj
就是this
上下文。 - 手动绑定。 这是你的一类函数,如
.bind
和.apply
。 这些你明确地陈述this
上下文是什么。 这些总是优先于前两个。
在你的例子中,你传递了一个函数引用,所以在它的调用中,它暗示着是一个全局函数或者没有上下文的函数。 使用.bind
通过在明确设置的地方创build一个新的函数来解决这个问题。
*这只在非严格模式下才是正确的。 在严格模式下, this
被设置为undefined
。
**假设你正在使用的function没有被手动绑定。
一种方法函数获取它们的上下文( this
)来自它们被调用的对象(这就是为什么method1
具有正确的上下文 – 它被调用)。 然后你传递一个函数本身的引用。 你可以想象,那么实现看起来像这样:
function then( callback ) { // assume 'value' is the recently-fulfilled promise value callback(value); }
在这个例子中, callback
是对你的函数的引用。 它没有任何上下文。 正如你已经注意到的,你可以通过绑定函数到上下文,然后再传递给它。