The prototype property of a JavaScript constructor function is one of the most often misunderstood aspects of JavaScripts OO paradigm. Luckily for everyone ES6's (ES2015) class
keyword makes the need for attaching methods directly to prototype
go away.
What about this?
It is common to see methods attached directly to this
instance within the constructor. Is this a bad thig? If your constructor is a singleton, then no, it is not a bad thing. But it is 2016 and you are creating components
with AngularJS, React, Vues.js, Polymer... whatever. These components are reusable class/constructors that may exist any number of times within a page.
Why is it bad?
When you define a method directly on this
within the constructor, that method is not an instance method, it is a unique copy of the method for each instance. This will have a memory impact because the method will be duplicated for each instance.
Let's say, for example, that we are going to create a MineSweeper app. For each cell in minesweeper we will create a component. Let's use AngularJS 1.5 for this example:
var app = require('../app');
app.component('Cell', {
bindings: {
cellId: '<'
},
controller: CellController,
templateUrl: 'cell.html'
});
CellController.$inject = ['CellMap'];
function CellController(cellCollection) {
this.onClick = function() {
cellCollection.landOn(cellCollection.cellId);
}
}
In the above contrived example the onClick
method would exist for each cell. If we have a 10 by 10 grid, we would have 99 more instances of this function than is needed.
We can clean this up.
CellController.$inject = ['CellMap'];
function CellController(cellCollection) {
this.cellCollection = cellCollection;
}
CellController.prototype.onClick = function() {
this.cellCollection.landOn(this.cellId);
}
This is OK. But using the new ES6 class syntax it becomes very clear.
CellController.$inject = ['CellMap'];
class CellController {
constructor(cellCollection) {
this.cellCollection = cellCollection;
}
onClick() {
this.cellCollection.landOn(this.cellId);
}
}
As you can see that is much clearer than the previous example. This is a contrived example purley for demonstration purposes. The above method would would not have much of a memory impact. But in the real world your component methods are not going to be one liners.
When can I use this.method = function() {}
If you are only using your controllers or compoents as a single instance you will have no benefit from having prototype or class methods other than having a single clear coding style standard.
If you are working on a team, or your code will outlive your involvement in a project -- it may be unclear why some controllers or components are binding methods to this
and some are using class instance methods.
Just for the sake of consistancy developers should be using instance methods in ES6 and prototype methods in ES5.