I know one of the difference is that instance variables of type Function automatically bind to the class. For example:
class Dog {
sound = 'woof'
bark() {
console.log(this)
}
boundBark = () => {
console.log(this)
}
}
const fido = new Dog()
fido.bark() // woof
fido.boundBark() // woof
const bark = fido.bark
bark() // undefined
const boundBark = fido.boundBark
boundBark() // woof
Dog { sound: 'woof', boundBark: [Function: boundBark] }
Dog { sound: 'woof', boundBark: [Function: boundBark] }
undefined
Dog { sound: 'woof', boundBark: [Function: boundBark] }
Why is this and are there other difference between these two ways of writing an instance function?
You can check what these ways are acting on the Dog.prototype
object:
Method definition:
class Dog {
bark() {
console.log(this) // *this* referss to the actual instance
}
}
console.log(Dog.prototype.bark); // function bark
class Dog {
bark = () => {
console.log(this); // also, *this* refers to the actual instance
}
}
console.log(Dog.prototype.bark); // undefined
In the first case you define a function in the class prototype, while in the latter you define the variable in the instance at "constructor time", as for any other variable.
The latter is the same as doing:
class Dog {
constructor() {
this.bark = () => {
// this is the reason why *this* is actually available
// and refers to the actual instance
console.log(this);
}
/* The rest of defined constructor */
}
}
console.log(Dog.prototype.bark); // undefined
Remember that the Public class field
s are still not introduced in the ECMAs
standards, so many JS environments could not support them, you should use some tools like Babel in order to achieve back compatibility. Some behaviours are still application dependant for this reason (like definition precedence).