Nifty Javascript - The Javascript Object Model

Object methods

By assigning functions to object properties, we can get the equivalent of methods in Javascript.

function Animal(sound) {
  this.makesound = function() { alert(sound) }
}

cow     = new Animal("Moooo.... !")
chicken = new Animal("Squawk...!")

It is very important to note that in the above, there are actually two separate instances of functions being created. The makesound property of each Animal instance points to its own copy of the anonymous function displaying the sound.

Thus,

function changechickensound() {
  chicken.makesound = function() {
                        alert("Cock...")
                        alert("a-doodle...")
                        alert("doo...!!")
                      }
}

changing the body of chicken.makesound() has no effect on cow.makesound().

The prototype property

If you want to emulate the more traditional object models found in Java, C#, C++, etc... you will need/want to have only one instance of each method created by the constructor. This approach also conserves memory. Javascript lets you accomplish this by means of the prototype property.

First, you have to realize that in Javascript, functions are also objects and thus have properties. One of the properties that all functions have is prototype. When you create an object via a constructor, it will inherit the properties of the prototype object of the [constructor] function used to create it.

// constructor
function Person(quote) { this.quote = quote }

// add properties to the prototype of the constructor
Person.prototype.action = "I said: "
Person.prototype.speech = function() {
  alert(this.action+this.quote)
}

// create object instances
nixon = new Person("I am not a crook!")
bush  = new Person("They misunderestimated me.")

One unique and really cool feature of Javascript is that when you change the prototype that a bunch of objects inherit from, all instances of those objects will now have the new values!

function changeSpeech() {
  Person.prototype.action = "I repeat: "
  Person.prototype.speech = function() {
    alert("I said: '"+this.quote+"'")
    alert(this.action+this.quote)
  }
}


Prototypal inheritance

In classless prototype-based languages, reuse and inheritance are accomplished in a natural manner via object cloning. In Javascript, you can create a helper function to get an easy syntax for doing this:

Object.prototype.clone = function () {
  function C() {}
  C.prototype = this
  return new C();
}
// All objects can now clone() themselves!

point1   = { x:10, y:25 }
point2   = point1.clone()
point2.x = 100
point2.z = 250
point3   = point2.clone()

Modifying an object that serves as prototype will have an immediate effect on all objects using that prototype:

function addvolumefunc() {
  point1.volume = function () { alert(this.x*this.y*this.z) }
}

As demonstrated above, point2 and point3 now have the volume() function we added to point1 since point1 serves the prototype of both. Of course, point2 is the immediate prototype of point3, however, prototypes are chained all the way back to their origin, so point3 still gets point1's volume().

Hint: point1.volume() returned NaN (not a number) because point1.z does not exist and thus this.x*this.y*this.z is undefined for it.


Shadowing in the prototype chain

Properties defined in the inheriting objects further down the prototype chain will 'shadow' earlier ones. You can see this demonstrated above with point2.x.

Now, we try to add the missing z to point1:

function addzToPrototype() { point1.z = 2 }

This means that point1.volume() can now compute a value. It should also mean that objects below point1 in the prototype chain should inherit its z. However... because point2 already defined its own z (like it did x), point1's newly created z remains invisible to point2 and all objects cloned from it. We have to delete() point2's z first:

...and now both point2 and point3 will start to use the value of point1's z.
(point1's x remains shadowed, of course.)

This is very similar to how attribute inheritance works in Python.


Visit Douglas Crockford's site for more on this topic.







Back to Table of Contents