this
is actually precisely === undefined
under strict mode in the second example. The difference is that all arrow functions close over the lexical this
value of the scope in which they are created.
In your first example:
export class Test {
x: {}; // Please stop using any.
processData = (data) => {
console.log("This=", this);
this.x = data;
console.log("Loaded.", data);
}
}
that lexical context is the instance of the enclosing class as you are defining an instance property, not a prototype method, the value of which is an arrow function closed.
In the second example:
export class Test {
x: {};// Please stop using any.
processData(data) {
console.log("This=", this);
this.x = data;
console.log("Loaded.", data);
}
}
You are creating a method on the class prototype. A method has a dynamically scoped this reference that is bound at invocation time when it is called.
If you call it as object.method()
, this
will refer to object
inside of method
for that invocation and that invocation only.
If you call it as method()
, that is with no receiving object, and if you running in strict mode, then this will be undefined
inside of method
for that invocation and that invocation only.
If you are not running in strict mode, this will refer to the global object. For example in a browser it will refer to window
. This is very bad. Always run in strict mode.
Code is implicitly in strict mode inside of ES Modules and class bodies. You can set strict mode explicitly by beginning the enclosing file or enclosing function with the 'use strict';
directive prologue.
That is why the code fails in your second example, because this
is undefined. In order to pass a method as a callback you need to bind it first.
That is to say you would write
ionViewLoaded() {
console.log("## ionViewDidLoad");
this.myApi.getPromise().then(this.processData.bind(this));
}
Alternately you could create an arrow function that closed over the instance and the method at use site as in
ionViewLoaded() {
console.log("## ionViewDidLoad");
this.myApi.getPromise().then(data => this.processData(data));
}
or just use an arrow function bound to a property as in your first example.
Oh, and if the comments didn't give you the hint, please do not annotate anything with the any
type.
I hope that helps.