Javascript Creation Patterns

I’ve taken a long break due to consulting work and a few lazy summer days. I’ve also taken a long break from writing any PHP but I’m itching to getting back to writing more PHP related articles. I just haven’t seen anything new with PHP lately except for some frameworks I haven’t dabbled with yet like Laravel, CodeIgniter and others. Perhaps I’ll find interest in these at a later time – it might worth dissecting these architectures, there’s always something new to learn.

Today though, I want to cover a few key concepts regarding Javascript Objects. I just felt like these need to be revisited time and time again. All credit goes to this channel and video – JavaScript object creation patterns tutorial – factory , constructor pattern, prototype pattern I’m simply highlighting some key concepts covered in this video. I found that this video does a pretty good job of covering javascript patterns.

Key concepts

So there are three key patterns I’ll be covering here. To give my examples some context, I’m using heroe’s to represent our sample objects. Here they are below –

  • Factory
  • Constructor
  • Prototype

Factory Pattern

The factory pattern is essentially defining function expression that takes in a few parameters.


// Factory pattern

var heroFactory = function(realName, heroName, mainPower) {

  // declare empty object
  var hero = {};

  hero.realName = realName;
  hero.heroName = heroName;
  hero.mainPower = mainPower;

  hero.summonHero = function() {

    console.log(this.heroName + ', Real Name: ' + this.realName + ', Powers & abilities: ' + this.mainPower);

  }

  return hero;

}

var ironMan = heroFactory('Tony Stark', 'Iron Man', 'Armor Suit');
ironMan.summonHero();

console.log('---------------------------');

var captainAmerica = heroFactory('Steve Rogers', 'Captain America', 'Super Soldier');
captainAmerica.summonHero();

console.log('---------------------------');

var thor = heroFactory('Thor', 'Thor Odinson', 'Demi-God');
thor.summonHero();

When I run the above program, this outputs the following:


Iron Man, Real Name: Tony Stark, Powers & abilities: Armor Suit
---------------------------
Captain America, Real Name: Steve Rogers, Powers & abilities: Super Soldier
---------------------------
Thor Odinson, Real Name: Thor, Powers & abilities: Demi-God

The Factory Pattern does exactly what the name implies, creates new objects or produces output much like a factory. We create new heroes by creating new objects and passing parameters accordingly. Here we’ve created 3 heroes – Iron Man, Captain America, and Thor Odinson. I find this pattern to be really straightforward while still providing a lot of flexibility. I’d like to get to the next pattern called the “Contructor Pattern”.

Constructor Pattern

For simplicity sake I’m going to use the same Hero example, but this time we will be summoning our heroes using function constructors. The main difference with this pattern is were are attaching our properties directly onto the function object itself instead of creating a temporary object. In other words, we are using the ‘this’ keyword to build our object. We also have to use the ‘new’ keyword so that our constructor can return an object. See our example constructor pattern below:


// Constructor pattern
  
var heroConstructor = function(realName, heroName, mainPower) {

  this.realName = realName;
  this.heroName = heroName;
  this.mainPower = mainPower;

  this.summonHero = function() {

    console.log(this.heroName + ', Real Name: ' + this.realName + ', Powers & abilities: ' + this.mainPower);

  }

}

var ironMan = new heroConstructor('Tony Stark', 'Iron Man', 'Armor Suit');
ironMan.summonHero();

console.log('---------------------------');

var captainAmerica = new heroConstructor('Steve Rogers', 'Captain America', 'Super Soldier');
captainAmerica.summonHero();

console.log('---------------------------');

var thor = new heroConstructor('Thor', 'Thor Odinson', 'Demi-God');
thor.summonHero();

When we run our program above, we get the same exact output. For formality sake – I’ll go ahead and provide the output below:

Iron Man, Real Name: Tony Stark, Powers & abilities: Armor Suit
---------------------------
Captain America, Real Name: Steve Rogers, Powers & abilities: Super Soldier
---------------------------
Thor Odinson, Real Name: Thor, Powers & abilities: Demi-God

As mentioned in the video though, there’s a downside to this – and I’m glad I tuned in to it. See, each time we construct and summon a new hero we use up some memory space. Each time we use the ‘new’ keyword to create a new hero we are recreating the same object properties and this is quite redundant. The negative impact isn’t noticeable when creating just three hero objects, but when we start creating a thousand heroes, this can have some negative implications in terms of performance and efficiency. This leads us to the next pattern – the “Prototype Pattern”.

Prototype Pattern

The prototype pattern still uses the concept of object creation but instead of creating an empty object (literal) inside a function object, we are going to create an empty function object first. Then we are going to start attaching properties and methods to it.

First though, let’s take a look at a preliminary prototype example before we dive into writing the entire program in its entirety.


// attaching a property to the function object itself
hero.summonHero = function() {
  return this.hero;
}

// attaching a property to the function objects prototype space
hero.prototype.summonHero = function() {
  return this.hero;
}

This method allows for adding properties and methods to the object on the fly after we have instantiated the object with the ‘new’ keyword. We shall see in the example below.


// Prototype pattern

// create empty function constructor
var heroProto = function() {}

// Attach methods and properties to our empty function
// these serve as defaults
heroProto.prototype.realName = 'no real name';
heroProto.prototype.heroName = 'no hero name';
heroProto.prototype.mainPower = 'no main power';

heroProto.prototype.summonHero = function() {

  console.log(this.heroName + ', Real Name: ' + this.realName + ', Powers & abilities: ' + this.mainPower);

}

var ironMan = new heroProto();
ironMan.realName = 'Tony Stark';
ironMan.heroName = 'Iron Man';
ironMan.mainPower = 'Armor Suit';
ironMan.summonHero();

console.log('---------------------------');

var captainAmerica = new heroProto();
captainAmerica.realName = 'Steve Rogers';
captainAmerica.heroName = 'Captain America';
captainAmerica.mainPower = 'Super Soldier';
captainAmerica.summonHero();

console.log('---------------------------');

var thor = new heroProto();
thor.realName = 'Thor Odinson';
thor.heroName = 'Thor';
thor.mainPower = 'Demi-God';
thor.summonHero();

Okay cool so we’ve gotten our feet wet with some pretty powerful patterns in Javascript. One of the main benefits to this pattern is that since we are attaching properties and methods to the objects prototype, newly constructed objects are lightweight thus improving efficiency and performance.

A few more things though – how do we verify a specific property exists as part of an object? Well thanks to javascript’s ‘in’ operator and ‘hasOwnProperty()’ method, we can easily find that out.

Let’s check and see if the property ‘heroName’ is a part of the ironMan object


console.log('heroName' in ironMan); // outputs true
console.log(ironMan.hasOwnProperty('heroName')); // outputs true

One last caveat to the prototype pattern – the major downside is that this approach lengthens our code. Moreover, we first have to create an empty object and then start attaching values to it at a later point in time. We basically can’t create everything in one line which can cause a lot of confusion once our objects gets very large. We can also improve memory space by making our prototype more lightweight. Thankfully, javascript allows for a flexible landscape – we can combine concepts from both the constructor and prototype pattern and implement a “Dynamic Prototype Pattern” below:


// Dynamic Prototype pattern

// create empty function constructor
var heroDynamicProto = function(realName, heroName, mainPower) {

  this.realName = realName;
  this.heroName = heroName;
  this.mainPower = mainPower;

    if ( typeof this.summonHero !== 'function') {

        heroDynamicProto.prototype.summonHero = function() {
                console.log(this.heroName + ', Real Name: ' + this.realName + ', Powers & abilities: ' + this.mainPower);

        }
  }

};

var ironMan = new heroDynamicProto();
ironMan.realName = 'Tony Stark';
ironMan.heroName = 'Iron Man';
ironMan.mainPower = 'Armor Suit';
ironMan.summonHero();

console.log('---------------------------');

var captainAmerica = new heroDynamicProto();
captainAmerica.realName = 'Steve Rogers';
captainAmerica.heroName = 'Captain America';
captainAmerica.mainPower = 'Super Soldier';
captainAmerica.summonHero();

console.log('---------------------------');

var thor = new heroDynamicProto();
thor.realName = 'Thor Odinson';
thor.heroName = 'Thor';
thor.mainPower = 'Demi-God';
thor.summonHero();

I’m looking forward to covering more advanced topics in Javascript, namely closures and ES6 classes. So stay tuned and please check back for new posts!