I was wondering - what is the difference between class method, class property which is a function and class property which is an arrow function? Does the 'this' keyword behave differently in the different variants of the method?
class Greeter {
constructor() {
this.greet();
this.greet2();
this.greet3();
}
greet() {
console.log('greet1', this);
}
greet2 = () => {
console.log('greet2', this);
}
greet3 = function() {
console.log('greet3', this);
}
}
let bla = new Greeter();
Edit: javascript output from the compiled typescript:
var Greeter = /** @class */ (function () {
function Greeter() {
var _this = this;
this.greet2 = function () {
console.log('greet2', _this);
};
this.greet3 = function () {
console.log('greet3', this);
};
this.greet();
this.greet2();
this.greet3();
}
Greeter.prototype.greet = function () {
console.log('greet1', this);
};
return Greeter;
}());
var bla = new Greeter();
My TypeScript version is 3.4.5
There are differences between all 3 versions. This differences are in 3 areas:
this
at runtimethis
in typescript.Lets start with where they work just the same. Consider this class, with a class field:
With this class all 3 function calls will print as expected:
'greet* me'
when invoked onbla
Who is this at runtime
Arrow functions capture
this
from the declaration context, sothis
ingreet2
is always guaranteed to be the class instance that created this function. The other versions (the method and function) make no such guarantees.So in this code not all 3 print the same text:
This is particularly important when passing the function as an event handler to another component.
Where the function is assigned
Class methods (such as
greet
) are assigned on the prototype, field initializations (such asgreet2
andgreet3
) are assigned in the constructor. This means thatgreet2
andgreet3
will have a larger memory footprint as they require an allocation of a fresh closure each timeGreeter
is instantiated.What is the type of this in typescript.
Typescript will type
this
as an instance ofGreeter
in both the method (greet
) and the arrow function (greet2
) but will typethis
as any ingreet3
. This will make it an error if you try to usethis
ingreet3
undernoImplictAny
When to use them
Use the method syntax if this function will not be passed as an event handler to another component (unless you use
bind
or something else to ensurethis
remains the instance of the class)Use arrow function syntax when your function will be passed around to other components and you need access to
this
inside the function.Can't really think of a good use case for this, generally avoid.
this
keyword difference:In the above all three have same
this
but you will see the difference when you will pass the method to another functions.But there is another difference that the first method is on the
prototype
ofclass
while other two are not. They are the method of instance of object.No they are not same things. As I mentioned that
greet2
andgreet3
will not be onGreeter.prototype
instead they will be on the instance itself. It mean that if you create1000
instances ofGreeter
their will be 1000 different method(greet2
andgreet3
) stored in memory for 1000 different instances. But there will a singlegreet
method for all the instances.See the below snippet with two instances of
Greeter()