How many ways an object can be created in javascript

7 ways to create objects in Javascript

Javascript is one of the few object oriented languages without classes. Nevertheless it is possible to create new objects choosing among several different techniques some of which may seem confusing to the newbies.
In this article I will go through seven different ways to create objects in Javascript, pointing out the pros and cons in each of them.
Before starting, it is worth remembering that a Javascript object is a simple collection of properties. Each property is a key-value pair. The value can be a primitive type, an object, or a function. Properties can be added, updated or removed at any time.

1. Object constructor

The simplest way to create an object is to use the Object constructor:

view plainprint?

  1. varperson = new Object();
  2. person.name= “Diego”;
  3. person.getName = function(){
  4. return this.name;
  5. };

The main advantage of this approach is its simplicity.
On the other hand, instantiating multiple objects of the same type leads to a lot of code duplication. Moreover, it is not a compact construct which means it is not intuitively straightforward in pointing out to where the object’s construction ends.

2. Literal notation

view plainprint?

  1. varperson = {
  2. person.name : “Diego”,
  3. person.getName : function(){
  4. return this.name;
  5. }
  6. }

While the literal notation is more compact and elegant than the Object constructor, it is still not reusable.

3. Factory function

The Factory function allows to encapsulate and re-use the logic for creating similar objects. It leverages any of the previous constructs for this.
Either:

view plainprint?

  1. varnewPerson=function(name){
  2. var result = new Object();
  3. result.name = name;
  4. result.getName = function(){
  5. return this.name;
  6. };
  7. return result;
  8. };
  9. varpersonOne = newPerson(“Diego”);
  10. varpersonTwo = newPerson(“Gangelo”);
  11. console.log(personOne.getName()); // prints Diego
  12. console.log(personTwo.getName()); // prints Gangelo

Or:

view plainprint?

  1. varnewPerson=function(name){
  2. return {
  3. person.name : name,
  4. person.getName : function(){
  5. return this.name;
  6. };
  7. };
  8. varpersonOne = newPerson(“Diego”);
  9. varpersonTwo = newPerson(“Gangelo”);
  10. console.log(personOne.getName()); // prints Diego
  11. console.log(personTwo.getName()); // prints Gangelo

Code re-use and encapsulation are the main advantages of this pattern.
Now suppose you have an object X at a certain point in your code. How do you determine if X is a person or not? You could use some ad-hoc technique but the most elegant approach would be to interrogate theinstanceOf operator.

4. Function Constructor

In Javascript it is possible to call any function with the new operator in front of it.
Given a function F, for new F():

  • a new empty object X is created.
  • X is set as context for F meaning throughout Fthis points to X.
  • X is returned as result of F

view plainprint?

  1. functionPerson(name){
  2. this.name = name;
  3. this.getName = function(){
  4. return this.name;
  5. };
  6. };
  7. varpersonOne = new Person(“Diego”);
  8. console.log(personOne.getName()); // prints Diego
  9. console.log(personOne instanceOf Person); // prints true
  10. console.log(personOne.constructor === Person); // prints true
  11. console.log(personOne instanceOf Object); // prints true

This time instanceof behaves the way we desired.

The constructor pattern is compact, reusable and gives a classical OO syntax.
Still, it is not perfect! In our example the field getName is a function. In Javascript functions are objects. Same function defined ten times means ten different objects created. Escalate this to a thousand and realize how much memory is being wasted!
It would be nice if all instances of Person share the same getName object, since this holds behavior and not data.

5. Prototype

Functions are very special in Javascript. They are objects, they can create other objects and they automatically get a field called prototype.
A prototype is a plain object with a single field, called constructor, pointing to the function itself.
What makes it special is that every object created through a function inherits the function’s prototype.

view plainprint?

  1. functionPerson(){};
  2. Person.prototype.name= “Diego”;
  3. varpersonOne = new Person();
  4. varpersonTwo = new Person();
  5. console.log(personOne.constructor == Person); // prints true
  6. console.log(personOne.name); // prints Diego
  7. console.log(personTwo.constructor == Person); // prints true
  8. console.log(personTwo.name); // prints Diego

Let’s see more in detail what happens:

  • Line 1:Person function is created. It automatically gets the prototype field.
  • Line 2: A field calledname is added to Person’s prototype.
  • Lines 3 and 4: Two instances of Person are created. They both get a field called__proto__pointing to Person’s prototype.
  • The last four lines show how the two objects share all properties present in Person’s prototype

Why is the name field accessible directly from the object and not through the __proto__ field?
In order to answer this, we first have to understand how property lookup works in Javascript.
Suppose you want to access a field called name in an object foo:

  • iffoo has a property name, the relative value is returned.
  • iffoo does not have a property name but __proto__ does, __proto__’s value is returned.
  • if neitherfoo nor __proto__ have the property, then __proto__’s prototype is checked. And so on…

Due to time and space constraints, I will not talk more about prototypes except emphasizing that not all Javascript implementations provide access to __proto__. Therefore, it is better if you never try to access it.

The prototype pattern solves the issues encountered within the function constructor.
On the other hand, the opposite problem arises: All instances share the same fields. This is good for functions, but not for the rest!

view plainprint?

  1. personOne.name = “Filippo”;
  2. console.log(personOne.name); // prints Filippo
  3. console.log(personTwo.name); // prints Filippo

6. Function/Prototype combination

The function/prototype combination, as you would imagine, takes advantage of both approaches 🙂

view plainprint?

  1. functionPerson(name){
  2. this.name = name;
  3. };
  4. Person.prototype.getName = function(){
  5. return this.name;
  6. };
  7. varpersonOne = new Person(“Diego”);
  8. varpersonTwo = new Person(“Filippo”);
  9. console.log(personOne.getName()); // prints Diego
  10. console.log(personTwo.getName()); // prints Filippo
  11. console.log(personOne.getName === personTwo.getName) //prints true

While sharing behavior (the getName function), each object has its own data and state.

7. Singleton

Sometimes, you may want to make sure that only a single instance of a certain class exists.
To get a Singleton in Javascript is as simple as defining and invoking the constructor at the same time:

view plainprint?

  1. varsingleton = new function(){
  2. this.name = “ApplicationName”;
  3. };

 

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s