Javascript 使用 Promise 时,为什么在类方法中未定义“this”?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/34930771/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Why is 'this' undefined inside class method when using promises?
提问by SteamDev
I have a javascript class, and each method returns a Q
promise. I want to know why this
is undefined in method2
and method3
. Is there a more correct way to write this code?
我有一个 javascript 类,每个方法都返回一个Q
承诺。我想知道为什么this
在method2
and 中未定义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;
};
I can fix this by using bind
:
我可以使用bind
以下方法解决此问题:
function MyClass(opts){
this.options = opts;
return this.method1()
.then(this.method2.bind(this))
.then(this.method3.bind(this));
}
But not entirely sure why bind
is necessary; is .then()
killing this
off?
但不完全确定为什么bind
是必要的;正在.then()
杀戮this
?
回答by lex82
this
is always the object the method is called on. However, when passing the method to then()
, you are not calling it! The method will be stored somewhere and called from there later. If you want to preserve this
, you will have to do it like this:
this
始终是调用该方法的对象。但是,当将方法传递给 时then()
,您并没有调用它!该方法将存储在某处并稍后从那里调用。如果你想保留this
,你必须这样做:
.then(() => this.method2())
or if you have to do it the pre-ES6 way, you need to preserve this
before:
或者如果你必须按照 ES6 之前的方式来做,你需要在this
之前保留:
var that = this;
// ...
.then(function() { that.method2() })
回答by Joseph
Promise handlers are called in the context of the global object (window
) by default. When in strict mode (use strict;
), the context is undefined
. This is what's happening to method2
and method3
.
window
默认情况下,在全局对象 ( )的上下文中调用 Promise 处理程序。在严格模式 ( 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
}());
For method1
, you're calling method1
as this.method1()
. This way of calling it calls it in the context of the this
object which is your instance. That's why the context inside method1
is the instance.
对于method1
,您正在调用method1
为this.method1()
。这种调用方式在作为this
您的实例的对象的上下文中调用它。这就是为什么里面的上下文method1
是实例。
回答by Mike Cluck
Basically, you're passing it a function reference with no context reference. The this
context is determined in a few ways:
基本上,您传递给它的是一个没有上下文引用的函数引用。该this
上下文在几个方面决定:
- Implicitly. Calling a global function or a function without a binding assumes a global context.*
- By direct reference. If you call
myObj.f()
thenmyObj
is going to be thethis
context.** - Manual binding. This is your class of functions such as
.bind
and.apply
. These you explicitly state what thethis
context is. These always take precedence over the previous two.
- 含蓄地。调用全局函数或没有绑定的函数假定全局上下文。*
- 通过直接引用。如果你打电话,
myObj.f()
那么myObj
将是this
上下文。** - 手动装订。这是您的函数类,例如
.bind
and.apply
。这些您明确说明this
上下文是什么。这些总是优先于前两个。
In your example, you're passing a function reference, so at it's invocation it's implied to be a global function or one without context. Using .bind
resolves this by creating a new function where this
is explicitly set.
在您的示例中,您正在传递一个函数引用,因此在调用它时,它暗示是一个全局函数或一个没有上下文的函数。Using.bind
通过创建一个this
明确设置的新函数来解决这个问题。
*This is only true in non-strict mode. In strict mode, this
is set to undefined
.
*这只适用于非严格模式。在严格模式下,this
设置为undefined
.
**Assuming the function you're using hasn't been manually bound.
**假设您使用的函数没有被手动绑定。
回答by James Allardice
One way functions get their context (this
) is from the object on which they are invoked (which is why method1
has the right context - it's invoked on this
). You are passing a reference to the function itself to then
. You can imagine that the implementation of then
looks something like this:
函数获取它们的上下文 ( this
) 的一种方式是从调用它们的对象中获取(这就是为什么method1
具有正确的上下文 - 它是在 上调用的this
)。您将对函数本身的引用传递给then
. 你可以想象它的实现是then
这样的:
function then( callback ) {
// assume 'value' is the recently-fulfilled promise value
callback(value);
}
In that example callback
is a reference to your function. It doesn't have any context. As you've already noted you can get around that by binding the function to a context before you pass it to then.
在该示例中callback
是对您的函数的引用。它没有任何上下文。正如您已经注意到的,您可以通过在将函数传递给 then 之前将函数绑定到上下文来解决这个问题。