Why use ES6 class or ES5 prototype?

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:

ES5
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.

ES5
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.

ES6
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.