Thursday April 24, 2014:

How to use the 'new' keyword

In my last post, we created examples for functional and functional-shared instantiation patterns. Today, we'll continue with those car examples for prototypal and pseudoclassical instantiation.

Additionally, you'll easily understand exactly what new does.


Prototypal Instantiation

TL;DR: A function that returns an object using Object.create() for prototype delegation.

Example:

var makeCar = function (color, vin) {  
    var carInstance = Object.create(carMethods);

    carInstance._carVIN = vin;
    carInstance.carColor = color;

     return carInstance;
};

var carMethods = {};

carMethods.seeVin = function () {  
    console.log('This car\'s VIN is ' + this._carVIN);
};

carMethods.engineSound = function () {  
    alert('Vroom vrooom!');
};

//instance
var car = makeCar('red', 12345);  

Here is the prototypal instantiated version of our car object:

car = {  
    _carVIN: 12345,
    carColor: red,

    seeVin: function () {
        console.log('This car\'s VIN is ' + this._carVIN);
    },

    engineSound = function () {
        alert('Vroom vrooom!');
    }
};

This object is almost identical to the functional-shared pattern above, except with a subtle and imporant distinction: the Object.create() method creates a new object from it's argument and creates delegation from our car instance to the carMethods object.

The difference between delegation and references:

var foo = 3;

var bar = foo;

foo = 5  

What is bar? Since the variable bar is assigned to the value of foo, bar is still 3.

bar --> foo --> 3  

Variables can only point to values, not other variables, so

bar --> 3  

foo was referring to the value of 3, then changed to the value of 5.

Line1: foo --> 3  
Line3: foo --> 5

foo;    //5  

Delegation, on the other hand, creates a delegation relationship because of the use of Object.create():

The Object.create() method creates a new object with the specified prototype object and properties. -Mozilla Developer Network

This means that makeCar.prototype no longer points to it's own inherent prototype object, but instead, points to a new prototype object, which points to carMethods.

Delegations

Now, if carMethods's functions are changed or deleted, the changes are propagated to all current and future car instances.

Conclusion:

  • No private variables in closure
  • Method and property changes in prototype affect all instances

Pseudoclassical Instantiation

TL;DR: A function that returns an object using the new keyword and allows for method and property delegation.

Our makeCar function using a pseudoclassical pattern:

var Car = function (color, vin) {  
    this._carVIN = vin;
    this.carColor = color;
};

Car.prototype.seeVin = function () {  
    console.log('This car\'s VIN is ' + this._carVIN);
};

Car.prototype.engineSound = function () {  
    alert('Vroom vrooom!');
};

var car = new Car('red', 12345);  

Here is a pseudoclassically instantiated version of our car object:

car = {  
    _carVIN: 12345,
    carColor: red,

    seeVin: function () {
        console.log('This car\'s VIN is ' + vin);
    },

    engineSound: function () {
        alert('Vroom vrooom!');
    }
};

By using this pattern, all car instances are will have their methods stored on Car's prototype method. Additionally, all of these methods are delegations, not references.

It's important to know what happens behind the scenes when new is used to instantiate with the pseudoclassical pattern.

In the above code, the commented out lines are what is happening in the background:

var Car = function (color, vin) {

    //this = Object.create(carMethods);

    this._carVIN = vin;
    this.carColor = color;

      //return this;

};

When a Car instance is instantiated, there are two implicit this keywords that help create the instance.

The first is this = Object.create(carMethods) . As mentioned above, Object.create() creates a delegation relationship with the prototype object passed in as it's argument.

this.carVin and this.carColor are added to this as properties.

Then the second implicit this is reached, where Car returns an instance of Car (car in this case) that has methods that delegate to it's methods. Any changed to Car's methods creates an immediate change in car's methods.


So pseudoclassical has the same result as the prototypal pattern? -Everybody

Yup.

Why are there two ways in the first place? -Haters

Well...good question. Brendan Eich created the first version of JavaScript in just 10 days. At that time, Java was very popular, and allowed users to create classes using a new keyword. Some say it was a marketing move to make the language like Java. Others haven't a clue.

Additionally, Object.create() is a relatively new (well..newer than new) method, and allows developers more flexibility when creating classes and inheritance patterns.