Just JavaScript - Object Construction
Written by Ian Elliot   
Thursday, 21 August 2014
Article Index
Just JavaScript - Object Construction
Late and early binding
The Constructor

Object creation is fundamental to all object-oriented languages, but in JavaScript is is left to the programmer to work out how best to do it and often the practice that you encounter isn't the best because it's borrowed from other languages. 

Just JavaScript 

 There is a newer version of the draft of the book here.

A Radical Look At JavaScript

Contents

  1. JavaScript Isn't Java, or C, or C# ... (Book Only)
  2. In The Beginning Was The Object
  3. The Function Object
  4. How Functions Become Methods
  5. The Object Expression
  6. Object Construction
  7. The Prototype
  8. Type And Non-Type
  9. Constructor And InstanceOf
  10. Duck Testing And Prototype Construction

-Preface-

Most books on JavaScript either compare it to the better known class based languages such as Java or C++ and even go on to show you how to make it look like the one of these.

Just JavaScript is an experiment in telling JavaScript's story "just as it is" without trying to apologise for its lack of class or some other feature. The broad features of the story are very clear but some of the small details may need working out along the way - hence the use of the term "experiment". Read on, but don't assume that you are just reading an account of Java, C++ or C# translated to JavaScript - you need to think about things in a new way. 

Just JavaScript is a radical look at the language without apologies. 

JustJavaScripticon

 

One of the most misunderstood parts of JavaScript is the way that objects are created. The reason is that JavaScript doesn't make use of the idea of class and programmers coming from other languages try to re-implement it. In a language that uses only object instances, reinventing class is a bit of a waste of time. 

Also the idea that JavaScript is a "prototype" based language is also misleading. The prototype is often introduced as a way of creating object hierarchies as in a class based language. In a language that doesn't make much of the idea of type object hierarchies are a so a bit a of a waste of time. 

So how do we create objects in JavaScript?

If you already know about JavaScript constructors read, on because how they are arrived at is an important story.

The Classical Constructor

It might help to look first at how class based languages deal with the problem of creating instances. If you don't know about class based languages work just skip to the next section. 

In class based languages instances of a class are generally created using the constructor which implicitly uses the class definition to manufacture an instance of the class.

For example in language like Java, C++ or C# you would write:

MyClass myObject = new myClass();

where myClass() is the constructor. The constructor is a function that returns an instance of the class. 

This is a fact that is often overlooked by programmers in class based languages because they don't actually have to write any thing in the constructor for it do do its job. That is an empty or default constructor will automatically do the job of creating an instance. This results in programmers thinking that constructors are really only needed when something has to be initialized or setup in some way. 

In fact the idea of a constructor can be extended to the idea of an object factory. An object factory is an object that will create another object - perhaps another instance of its own type or another completely different type.

The idea of a function which creates objects is core to class based languages and to all object oriented languages. 

The JavaScript Object Factory

If you just want a single object then you could simply make use of an object literal and define your object. 

For example:

var myObject={prop1:object1,prop2,object2... }

This works perfectly well and it is a good way to make a singleton object - i.e. an object that there should only be one instance of in any given program. 

For example if you want to store the position of a single 2D point you might define:

var myPoint={x:0,y:0};

However if you want more than one copy of an object you need to automate the creation or implement a method of cloning an existing object. Although cloning is a perfectly proper way to create new instances of objects it isn't the most usual way of going about the task. In JavaScript the standard practice is to use an object factory and to be more precise a constructor. Let's take a look a the object factory approach first and then see how it specializes into a constructor. 

An object factory is any function that returns a single object as its result. As a function in JavaScript is just an executable object it sometimes helps to think of an object factory as an object that creates an instance of another object. 

How do object factories work?

At their very simplest an object factory creates an object literal and returns it as its result.  

For example an object factory for the point object is:

Point=function(){
 return {x:0,y:0}; 
};

and to use it to create an instance of the Point object you would use:

var myPoint=Point();

It seems trivial yet in no time at all it can become complicated and subtle. 

Notice that we already have recreated one of the minor problems of a class based language - finding a name for the class and for an instance. In this case the naming problem is finding something to call the object factory and then names for the instances - i.e. Point and myPoint. Perhaps it would be better to call the factory PointMaker or something to indicate that it wasn't actually an instance of a Point object. 

As the object being created gets bigger and more complicated, building it in smaller steps becomes a better method. Starting from an empty object you can add properties one by one. 

For example:

Point=function(){
 var obj={};
 obj.x=0;
 obj.y=0;
 return obj;
};

One of the big advantages of using an object factory is that you can use parameters to customize the object produced. 

For example:

Point=function(x,y){
 var obj={};
 obj.x=x;
 obj.y=y;
 return obj;
};

and you create the object using:

var myPoint=Point(1,2);

The ability to customize object instances is one of the big plus points of using an object factory.  It is so useful that an object factory is often used to create a singleton - even though the factory will only ever create a single object. 

Constructing Methods

Of course the object that the factory produces can have any type of object as its properties including Function objects.

As already explained in Just JavaScript - How Functions Become Methods, Function properties aren't really the same thing as methods.

To make a Function property act like a method you have to make use of the this call context, i.e. this, to specify the instance that is being referenced. 

If you are creating an object as an object literal there is no other choice but to use this to create a late bound method for an object. 

However if you are using a factory function there is an alternative and it is arguably better as it creates an early bound method.

For example, suppose we want to write a method that adds x and y together:

Point=function(x,y){
 var obj={};
 obj.x=x;
 obj.y=y;
 obj.add=function(){
          return obj.x+obj.y;
         };
 return obj;
};

Notice that the function uses obj.x and obj.y not just x and y. 

If you try out 

var myPoint=Point(1,2);
myPoint.x=4;
alert(myPoint.add());

you will find it works and displays 6 - but how can it?

When myPoint.add is called, the variable obj has long gone as the factory object's code has terminated and all its variables have been destroyed. How can a Function object make use of the factory's obj variable long after it has been destroyed? 

The answer, of course, is closure.

If you recall, closure in JavaScript is necessary to resolve the problem of having Function objects which live for longer than their code. When you define the add Function object it captures the variables that are in scope at the time of its creation, i.e. obj. Thus the add function has access to obj even though, without closure, it should have been destroyed.

Also notice that code in other Function objects can't access the obj variable because it no longer exists and it is local to the factory function. That is, obj is a private variable for the instance of the point object we have created. 

The general rule is that any local variables declared within the object factory are turned into private variables for the object created by closure.

This is another advantage of using an object factory even for a singleton. Object literals don't have private variables unless they are created within a function. 



Last Updated ( Sunday, 10 May 2015 )