JavaScript's class-less objects

by Stoyan Stefanov

Java and JavaScript are very different languages, although the similarity in the names and the similar C-like syntax confuses people sometimes. Let's take a look at one pretty major difference and that is how objects are created. In Java, you have classes. Then objects, a.k.a. instances, are created based on those classes. In JavaScript, there are no classes and objects are more like hash tables of key-value pairs. Then what about inheritance? OK, one step at a time.

JavaScript objects

When you think about a JavaScript object, think a hash. That's all there is to objects - they are just collections of name-value pairs, where the values can be anything including other objects and functions. When an object's property is a function, you can also call it a method.

This is an empty object:

var myobj = {};

Now you can start adding some meaningful functionality to this object:

myobj.name = "My precious";
myobj.getName = function() {return this.name};

Note a few things here:

Another way to create an object and add properties/methods to it at the same time is like this:

var another = {
  name: 'My other precious',
  getName: function() {
    return this.name;
  }
};

This syntax is the so-called object literal notation - you wrap everything in curly braces { and } and separate the properties inside the object with a comma. Key:value pairs are separated by colons. This syntax is not the only way to create objects though.

Constructor functions

Another way to create a JavaScript object is by using a constructor function. Here's an example of a constructor function:

function ShinyObject(name) {
  this.name = name;
  this.getName = function() {
    return this.name;
  }
}

Now creating an object is much more Java-like:

var my = new ShinyObject('ring');
var myname = my.getName(); // "ring"

There is no difference in the syntax for creating a constructor function as opposed to any other function, the difference is in the usage. If you invoke a function with new, it creates and returns an object and, via this, you have access to modifying the object before you return it. By convention, though, constructor functions are named with a capital letter to distinguish visually from normal functions and methods.

So which way is better - object literal or constructor function? Well, that depends on your specific task. For example, if you need to create many different, yet similar objects, then the class-like constructors may be the right choice. But if your object is more of a one-off singleton, then object literal is definitely simpler and shorter.

OK then, so since there are no classes, how about inheritance? Before we get there, here comes a little surprise - in JavaScript functions are actually objects.

(Actually in JavaScript pretty much everything is an object, with the exception of the few primitive data types - string, boolean, number and undefined. Functions are objects, arrays are objects, even null is an object. Furthermore, the primitive data types can also be converted and used as objects, so for example "string".length is valid.)

Function objects and prototype property

In JavaScript, functions are objects. They can be assigned to variables, you can add properties and methods to them and so on. Here's an example of a function:

var myfunc = function(param) {
  alert(param);
};

This is pretty much the same as:

function myfunc(param) {
  alertparam);
}

No matter how you create the function, you end up with a myfunc object and you can access its properties and methods.

alert(myfunc.length);     // alerts 1, the number of parameters
alert(myfunc.toString()); // alerts the source code of the function

One of the interesting properties that every function object has is the prototype property. As soon as you create a function, it automatically gets a prototype property which points to an empty object. Of course, you can modify the properties of that empty object.

alert(typeof myfunc.prototype); // alerts "object"
myfunc.prototype.test = 1; // completely OK to do so

The question is how is this prototype thing useful? It's used only when you invoke a function as a constructor to create objects. When you do so, the objects automatically get a secret link to the prototype's properties and can accees them as their own properties. Confusing? Let's see an example.

A new function:
function ShinyObject(name) {
  this.name = name;
}

Augmenting the prototype property of the function with some functionality:

ShinyObject.prototype.getName = function() {
  return this.name;
};

Using the function as a constructor function to create an object:

var iphone = new ShinyObject('my precious');
iphone.getName(); // returns "my precious"

As you can see the new objects automatically get access to the prototype's properties. And when something is getting functionality "for free", this starts to smell like code reusability and inheritance.

Inheritance via the prototype

Now let's see how you can use the prototype to implement inheritance.

Here's a constructor function which will be the parent:

function NormalObject() {
  this.name = 'normal';
  this.getName = function() {
    return this.name;
  };
}

Now a second constructor:

function PreciousObject(){
  this.shiny = true;
  this.round = true;
}

Now the inheritance part:

PreciousObject.prototype = new NormalObject();

Voila! Now you can create precious objects and they'll get all the functionality of the normal objects:

var crystal_ball = new PreciousObject();
crystal_ball.name = 'Ball, Crystal Ball.';
alert(crystal_ball.round); // true
alert(crystal_ball.getName()); // "Ball, Crystal Ball."

Notice how we needed to create an object with new and assign it to the prototype, because the prototype is just an object. It's not like one constructor function inherited from another, in essence we inherited from an object. JavaScript doesn't have classes that inherit from other classes, here objects inherit from other objects.

If you have several constructor functions that will inherit NormalObject objects, you may create new NormalObject() every time, but it's not necessary. Even the whole NormalObject constructor may not be needed. Another way to do the same would be to create one (singleton) normal object and use it as a base for the other objects.

var normal = {
  name: 'normal',
  getName: function() {
    return this.name;
  }
};

Then the PreciousObject can inherit like this:

PreciousObject.prototype = normal;

Inheritance by copying properties

Since inheritance is all about reusing code, yet another way to implement it is to simply copy properties.

Imagine you have these objects:

var shiny = {
   shiny: true,
   round: true
};

var normal = {
  name: 'name me',
  getName: function() {
    return this.name;
  }
};

How can shiny get normal's properties? Here's a simple extend() function that loops through and copies peoperties:

function extend(parent, child) {
  for (var i in parent) {
    child[i] = parent[i];
  }
}
extend(normal, shiny); // inherit
shiny.getName(); // "name me"

Now this property copying may look like overhead and not performing too well, but truth is, for many tasks it's just fine. You can also see that this is an easy way to implement mixins and multiple inheritance.

Crockford's beget object

Douglas Crockford, a JavaScript guru and creator of JSON, suggests this interesting begetObject() way of implementing inheritance:

function begetObject(o) {
  function F() {}
  F.prototype = o;
  return new F();
}

Here you create a temp constructor so you can use the prototype functionality, the idea is that you create a new object, but instead of starting fresh, you inherit some functionality from another, already existing, object.

Parent object:

var normal = {
  name: 'name me',
  getName: function() {
    return this.name;
  }
};

A new object inheriting from the parent:

var shiny = begetObject(normal);

Augment the new object with more functionality:

shiny.round = true;
shiny.preciousness = true;

YUI's extend()

Let's wrap up with yet another way to implement inheritance, which is probably the closest to Java, because in this method, it looks like a constructor function inherits from another constructor function, hence it looks a bit like a class inheriting from a class.

This method is used in the popular YUI JavaScript library (Yahoo! User Interface) and here's a little simplified version:

function extend(Child, Parent) {
  var F = function(){};
  F.prototype = Parent.prototype;
  Child.prototype = new F();
}

With this method you pass two constructor functions and the first (the child) gets all the properties and methods of the second (the parent) via the prototype property.

Summary

Let's quickly summarize what we just learned about JavaScript:

Author and credits

Stoyan Stefanov is a senior Yahoo! developer, YSlow tool lead, open-source contributor, blogger and technical writer, most recently the author of "Object-Oriented JavaScript" published by Packt.

The theme for the shiny object examples are inspired by Jim Bumgardner's Theory of the Precious Object

Douglas Crockford's beget object - article here