Why is 'this' undefined inside class method when using promises?
Basically, you're passing it a function reference with no context reference. The this
context is determined in a few ways:
- 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.
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.
*This is only true in non-strict mode. In strict mode, this
is set to undefined
.
**Assuming the function you're using hasn't been manually bound.
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
.
;(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.
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:
.then(() => this.method2())
or if you have to do it the pre-ES6 way, you need to preserve this
before:
var that = this;
// ...
.then(function() { that.method2() })