OOP in JavaScript ES5 & ES6

Written by  on September 26, 2015 

I’ll have one advice, to learn JS : just forget what you know about programming.

That especially includes the this keyword, OOP, Classes, Objects, Methods …. If you can clear such notions from your mind, you will be ready to understand what JS is :

var person = {"name" : "Bobby"}
var greet = function (end) {
 console.log("Hello " + this.name + end);
}
greet.call(person, "!");
//Prints : Hello Bobby!

person uses the built-in type Object : that is a associative array, an association of unique keys with they respective values. In the example, person has a property (key) called ‘name’ that references the value “Bobby”.

greet uses the built-in type Function : a bit of code that can be invoked. You can notice than the function has a property call that let us apply a value to the this keyword and other expected arguments. We’re setting the value of this inside greet and we’re calling it. Without using Function.call the value of this.name would have been undefined.

That’s what’s important to understand first : in JS a Function is a callable Object we can bind data to.

If one can grasp this concept he will save some time and headache learning JS by trying to apply notions like OOP. It has never been designed in such ways.

OOP is still possible IN ES5. Nevertheless hackey since we need to emulate/redesign it and it might be limited compared to what is possible in other OOP languages.

JS ECMAScript 5 ‘s OOP

In ES5,  one way is to use Functions to define classes and we define their prototypes to emulate inheritance.

//Defining public inherited members
//through prototype
Game.prototype.title = null;
//Game constructor
function Game(title) {
	this.title = title;
}

//Declaring Game as the base class of CardGame
CardGame.prototype = Game.prototype;

//CardGame constructor
function CardGame(title) {
	//variables declared with var keywords
	//are private
        //var self refers to current instance being created         //since we need to use 
        //it in private method shuffleGame
	var self = this;
	var cards = []

	//Calling super constructor
	CardGame.prototype.constructor.call(this, title);

	//Public method with private access
	//Although not inherited 
        //because not defined on prototype
	this.initGame = function() {
		shuffleCards();
	}

	//private function
	//alternative way of declaring it
	//var shuffleCards = function() {}
	function shuffleCards() {
		//Shuffle cards
		for(var i=0; i < self.cards.length; ++i) {

		}
	}
}

var poker = new CardGame("Poker");
poker.initGame();
console.dir(poker);

The variable self _this, that …)  an unavoidable technique of JS ES5’s OOP

We need the value of this from the CardGame function to reuse it in its function-properties and emulate a class and its  methods. Since we are not using Function.call(thisArg,arg…) the default behaviour is the keyword this refers to the object in which it is used (unless in strict mode it will be undefined). That’s why we are using a homemade self keyword to emulate OOP and access the instance from its methods.

Don’t forget the new keyword / Object.create

What we want is a sort of constructor function that returns a newly instantiated object well that is possible with the new keyword. Alone, CardGame is just a function that does stuff on itself and return nothing right? Well if we just write poker = CardGame(“Poker”) we’ll end up with the same object over and over hence the new keyword. An alternative is Object.create

Public/Private method emulation in ES5

If we declare a function as a property of the CardGame function it will be accessible from the outside. If we declare a var as a function inside the CardGame function then it will become private and only accessible from CardGame function. That is how we emulate public and private methods in ES5.

JS ECMAScript 6 ‘s OOP

Thanks to ECMAScript 6 Harmony include OOP sugar syntax, with the well-known notion of classes. Now in ES6 we can write :

class Game {
    constructor(title) {
        this.title = title;
    }
}
class CardGame extends Game {
    constructor(title) {
        super(title);
        this.cards = [];
    }
    initGame() {
        this.shuffleCards();
    }
    shuffleCards() {
        //Shuffle cards
        for (let i = 0; i < this.cards.length; ++i) {
        }
    }
}
let poker = new CardGame("Poker");
poker.initGame();
console.dir(poker);

Notice, we lose the ability to define private members. Since inside the class’s curly brackets we can only define method and only through these, we can define properties. Also all methods inside a class are public. There are work-arounds, in ES6, to create private members like Symbols, weak-map or closures… ES7 will solve this by introducing a private keyword.

Another feature ES6 brings is the let keyword. This statement declares a block scope local variable. It is pretty similar to var statement except the variable’s scope declared with let is limited to the block.

In addition if let redeclares the variable name in the same block, it will throw an error whereas var will reuse the same variable.

function CounterVar() {
    var objectPool = [];
    var count = -1;
    //same var
    for (var count = 0; count < objectPool.length; ++count) {
         //still the same var
         var count = null;
     }
}
function CounterLet() {
    var objectPool = [];
    let count = -1;

    //different variable
    for (let count = 0; count < objectPool.length; ++count) {
        //Will throw an error
        //because count already declared in code block
        let count = 0;
    }
}

Category : I.T

Tags :

Leave a Reply

Your email address will not be published. Required fields are marked *