Like it!

Join me on Facebook!

Like it!

Object literals vs constructors in JavaScript

I want to use JavaScript in a more object-oriented way.

JavaScript is, quite surprisingly, an object-oriented programming language that can be confusing when it comes to object creation. In this article I want to sort it out for good.

Literals and constructors

In JavaScript there are two ways to create an object: the constructor function or the literal notation. Take a look below:

// constructor function
function Website() {};

// literal notation
var Website = {};

Either way you have just created a JavaScript object called Website. The main difference here is what you can do with it. With the constructor function notation you create an object that can be instantiated into multiple instances (with the new keyword), while the literal notation delivers a single object, like a singleton.

Defining methods and properties

Objects in JavaScript have methods and properties, whether they are built with the constructor function or with the literal notation. Let's see how to define them:

// constructor function
function Website() {
    this.url = 'http://www.internalpointers.com';
    this.printUrl = function() {
        console.log(this.url);
    };
};

// literal notation
var Website = {
    'url': 'http://www.internalpointers.com',
    'printUrl': function() {
        console.log(this.url);
    }
};

Using the objects

Besides the syntax, the two objects differ in how you use them. If the object has been created with the constructor function, you must instantiate it first. On the other hand the literal-notated one is ready for use:

// constructor function
var InternalPointers = new Website();
InternalPointers.printUrl();

// literal notation
Website.printUrl();

Where's the constructor of literal notation?

It is clear that with the literal notation you can't have a constructor, namely you can't initialize your object unless you add a custom init() function. Instead, with the constructor function you can pass additional parameters to the object through the built-in constructor, like that:

// constructor function
function Website(protocol) {
    this.protocol = protocol;
    this.url = this.protocol + '://www.internalpointers.com';
    this.printUrl = function() {
        console.log(this.url);
    };
};

var InternalPointersHttp  = new Website('http');
var InternalPointersHttps = new Website('https');
InternalPointersHttp.printUrl();   // http://www.internalpointers.com
InternalPointersHttps.printUrl();  // https://www.internalpointers.com

Instantiation versus singleton approach

The previous snippet reveals another important property: with the constructor function you can instantiate how many objects you want, and they will be all unique. With the literal notation you always deal with the original object (which is a singleton, remember?), even if you define a new variable with the object as value:

// literal notation
var original = { 
    'property' : 'original' 
}

console.log(original.property); // 'original'

var clone = original;
clone.property = 'clone';

console.log(original.property); // 'clone' >:(

What about private and public stuff

Having private members with the literal notation is quite a pain in the ass, so let me leave it aside for now. Just think of literal-notated objects as lightweight containers where all members are public. For constructor functions things are easier, thanks to the concept of closure. This is how you set up a constructor function with a couple of private members:

// constructor function
function Website() {

    // private members
    var privateUrl = 'http://www.internalpointers.com';
    var privatePrint = function() {  
        console.log(privateUrl);
    };

    // public members
    this.printUrl = function() {
        privatePrint();
    };
};

var InternalPointers = new Website();
InternalPointers.printUrl();               // 'http://www.internalpointers.com'
InternalPointers.privatePrint();           // TypeError: InternalPointers.privatePrint is not a function
console.log(InternalPointers.privateUrl);  // undefined

Sources

Envato Tuts - The Basics of Object-Oriented JavaScript (link)
Stackoverflow - Should I be using object literals or constructor functions? (link)
Stackoverflow - How to add private variable to this Javascript object literal snippet? (link)
MDN - Object (link)
Douglas Crockford - Private Members in JavaScript (link)

comments