Join us on Facebook!
— Written by Triangles on June 20, 2016 • updated on November 13, 2017 • ID 39 —
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.
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.
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);
}
};
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();
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
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' >:(
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
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)
Started out with JS as a kid and have just tried to pick it up again after learning OOP. This clears so much up for me.
var website = new function( param ){ var private_data = param;
... etc } (5);
An arg at the end of the function definition means the function executes (and presumably returns something useful) immediately, thus silly looking IIFE syntax is never needed.
Later you could go : var x = new website(12); and create new instances as needed;
Because you can and generally should return either this, an object literal that defines a specific api or a function that itself returns an object (the most flexible and powerful method), the class syntax in ECMA 6 is redundant and only adds confusion to capability that has been in the language for years.