On objects, classes and prototypes in JavaScript

When developers from other languages start to use JavaScript more frequently one of the biggest stumbling blocks is trying to apply classical OO methods to JavaScript development. I’d like to go through the different options available and try clear up some of the confusion surrounding objects, classes and prototypes – once and for all.

Object Literals

These objects are probably the most frequently used because of their ease of creation and use. They are a way of storing or passing a group of values and methods together in one convenient entity. The syntax is as follows:

var me = {
  name: 'james', 
  age: 37, 
  isOld: function() {
    return this.age < 40
  }
};
alert(me.isOld()); //alerts false

Underneath, objects are just a hash-table, with a key and value. It is perfectly valid syntax to refer to members in an object using array syntax eg:

alert(me['name']); //alerts 'james'

Objects are also mutable in JavaScript which simply means you can add members to them after they have been defined:

me.greet = function() {
  return 'Hello ' + this.name;
}; //returns 'Hello james'

Another function greet was added to the object. We use the this keyword to refer to the object from inside one of the object’s own methods.

Constructor functions

What happens however when you want to store information about more than one person? In classical OO, this is where classes come in – you define a ‘template’ which can be used to create a object of a certain type with all the methods and properties filled in ready to be used.

JavaScript is a functional language, so it makes sense perhaps that the solution comes in the form of a type of function called a constructor function. A constructor function works by combining the new keyword with a function used to create a new object every time it is called.

Lets create a Person constructor function:

function Person(name, age) {
  this.name = name;
  this.age = age;
  this.isOld = function() {
    return this.age < 30
  }
}

In the example, Person looks like a normal function – because it is. Note that by convention constructor function names begin with a capital letter. The constructor is called when an object is created using the new keyword. Lets create two new objects:

var me = new Person('james', 37);
var you = new Person('visitor', 22);
alert(me.isOld()); //alerts true
alert(you.isOld()); // alerts false

We can use the Person constructor function to create as many people objects as we need.

Prototypes

In classic OO languages, objects tend to inherit from a base class, usually named object, which then provides a base level of useful functionality. JavaScript has a similar concept, but because it is classless each object has an underlying object instance instead. This is called the prototype. The prototype object contains all the base methods and properties in one place only, and only when these are updated are the members set at the top level of the inheritance chain.

Looking at our example above, we should move the isOld function to the prototype of Person as this means it is referenced in one place only. The code becomes slightly less readable as follows:

function Person(name, age) {
  this.name = name;
  this.age = age;
};
Person.prototype.isOld = function() {
  return this.age < 30
};

In this way, we split the constructor function and the prototype’s functions.

Prototypes and inheritance

What if we wanted to create a more specialised version of a Person – perhaps an Employee to inherit from Person. This is where JavaScript’s prototypal inheritance comes to the fore. WE inherit by setting a constructor function’s prototype before creating an object. This is best explained by example – lets first create an Employee constructor function:

function Employee(name, age, salary) {
  this.salary = salary;
}

We have added a salary property to Employee, now to add the magic sauce that makes an Employee ‘inherit’ from Person:

function Employee(name, age, salary) {
  Employee.prototype.call(this, name, age);
  this.salary = salary;
}
Employee.prototype = new Person();

Two things are happening here. Firstly the prototype. We provide the Employee constructor function with a single instance of Person, created with the new keyword, but without any parameters. When a method or property is not found on Employee the inheritance chain – in this case Person – is checked for the member requested and if it exists, is returned as if it were a member of Employee. Importantly, when a member value is set, the value is set directly on the target object, so that any underlying members are not overwritten. Potentially, this makes prototypal inheritance very efficient.

Secondly, we need a way of passing the age and salary parameters the Person constructor function. This is done by manually calling the prototype’s constructor with the correct context using the call function.

Inconsistencies within the prototypal inheritance model

If you step the code, or if you are eagle eyed, you’ll notice a potential problem with parameters and constructor functions. The Person constructor is called twice. Once when the prototype object is created, and once more when we actually want to call the constructor with parameters for a particular instance. Is this a design flaw, or should we adjust our way of thinking when using prototypal inheritance? I would argue for the latter, given that methods should be (mostly) defined in the prototype and – in our example at least – the name and age properties will continue to be undefined as they were before.

My biggest gripe with prototypal inheritance is not the implementation – though Douglas Crockford would argue that there is little need for a classical model in JavaScript at all.

I would however recommend a cleaner, more organised syntax for organising both the constructor and prototype code based around a function I’ve created called type


var Person = type({
  _constructor: function(name, age) {
    this.name = name;
    this.age = age;
  },
  _prototype: function() {
    this.isOld = function() {
      return this.age < 30;
    }
  };
})

var Employee = type(Person, {
  _constructor: function() {
    this.prototype.call(this, name, age);
    this.salary = salary;
  }
});

The type function creates a necessary layer of abstraction around the process. It combines the clean and simple brevity of an object literal, with the power to define a constructor and prototype all in one location, without having to worry about the semantics of prototypal inheritance later in the code. The code to enable this functionality is also neat and concise:

window.type = function(o, c) {
  if (arguments.length === 1) c = o, o = null;
  if (o) F.prototype = new o();
  return F;
		
  function F(){
    if (c._constructor) c._constructor.apply(this, arguments);
    if (c._prototype) c._prototype.call(F.prototype);
  }
}

On objects, classes and prototypes in JavaScript

A lightweight script loader

Script loaders are the Javascript blogosphere topic de jour and so I thought I’d weigh in with my own contribution. Use a script loader to delay the download and execution of portions of your page’s Javascript code, increasing page render/load performance. Script loaders originated with performance guru Steve Souders and some excellent libraries have sprung up as a result of his work.

Most script loading libraries I’ve looked quickly become over-complicated, whereas I wanted to make something ultra-light, and easy to use. Here’s a simple technique I use because the code is neat and should address 80% of requirements. It’s based on Steve’s asynchronous script loading technique, with some code added to attach a callback function once all scripts have loaded.

The script loader should be called as follows:

loadScript('script1.js', 'script2.js', function() {
  //code to run when both scripts have been loaded
});

The function works by placing a correctly formatted script tag into the header of the page and attaching a load handler to each script to enable the execution of a callback (if required). I like this technique because debugging tools such as Firebug continue to work as normal, respects any cache settings, but still provides the performance parallel script downloading – plus its seriously lightweight.

To create dependancy chains, use the function like so:

loadScript('script1.js', 'script2.js', function() {
  loadScript('script3.js', function() {
    //Execute code 
  });
});

You can view the source code here.

A lightweight script loader

Namespaces with JavaScript

If you develop a page containing multiple javascript files theres a good chance that sooner or later you are going to declare a function or variable with the same name in multiple files – breaking your code and causing a bug that could be hard to trace. The solution is to place your code inside another uniquely named object, or even chain of objects – called a namespace. A simple solution could look like this:

acme.sales.js

if (acme == null) acme = {};
if (acme.sales == null) acme.sales = {};

acme.sales.addTarget = function() {
  ...
}


acme.marketing.js

if (acme == null) acme = {};
if (acme.marketing == null) acme.marketing = {};

acme.marketing.addTarget = function() {
  ...
}

This ensures that the second addTarget function doesn’t overwrite the first.

However, we can improve this code pattern by creating a function. This allows us to take advantage of the this keyword inside the function:

acme.marketing 2.0.js

if (acme == null) acme = {};
if (acme.marketing == null) acme.marketing = new function() {
  this.addTarget = function() {
    ..
  }
};

This also provides a useful way of creating public and private methods:

if (acme == null) acme = {};
if (acme.marketing == null) acme.marketing = new function() {
  this.addTarget = function() {
    ..
  }

  //Private functions
  var internal = function() {
    ..
  }
};

The public function addTarget is visible to the namespace, but the internal function isnt.

The namespace function

The namespace function takes these ideas and makes the code more succinct and readable. Using the namespace function, we could rewrite our examples so:

namespace('acme.sales', function() {

  this.addTarget = function() {
    ..
  }
}

namespace('acme.marketing', function() {

  this.addTarget = function() {
    ..
  }
  var internal = function() {
    ..
  }
}

All parent namespaces are created if they dont exist and the namespace is only declared in one place, making it much easier to change if required. If the namespace already exists, you can use the object directly instead of the string representation.

View code

Namespaces with JavaScript

Introducing jQuery superpng plug-in

The superpng plug-in has been written to provide a flexible png alpha api to developers using jQuery and who need to support IE6. Other scripts didn’t provide the performance, features or flexibility that I required, as well as not using functionality available in jQuery which is fairy ubiquitous these days. The script uses either the AlphaImageLoader filter or the vml approach, depending on the type of tag and whether background-position is required.

For more information on alpha pngs and IE6, please see my previous post here.

Usage

Enable alpha images for all elements with a class of .png providing the relative path of the replacement transparent gif image:

$(document).ready(function() {
	$('.png').superpng({path: '../images/blank.gif'});
});

The full list of options are as follows:

  • path: define the location of the transparent .gif file used to replace the original png image
  • mode: filter/vml/auto (default) – describes the method used to enable png alpha.
    • filter:  The alpha loader fix is used, replacing the existing image with the blank image found in path.
    • vml: vml markup is placed inside the container. Requires a <div> or other block element.
    • auto:  A mode is chosen based on the tag type and background-position value.
  • cache: Determines if background images are cached. Default true.

Superpng is licenced under the the MIT, BSD, and GPL Licenses. Online examples are available here and the code is available on Github.

Please contact me with any feedback or any issues you may encounter.

Introducing jQuery superpng plug-in

Transparent .png images in IE6

A lot of web design I’m involved with these days involves either animating images over backgrounds, or creating composite layouts made up of multiple layered images. These techniques require placing images over one another, and blending the images (usually with shadows) together. This approach requires images with something called alpha (partial) transparency. The alpha channel is a separate stream of data that specifies the level of transparency for each pixel in the image. In web browsers this functionality is available as a 24 bit .png, with 8 bits each for alpha, red, green and blue.

Now for the kicker. Alpha transparency isn’t available in IE6, and unfortunately as I write this, corporate customers still dictate that we support Microsoft’s finest browser creation.

As has been documented for some time, certain workarounds exist for displaying transparent images in IE6. Firstly, the original sleight method used the proprietary alpha image loader filter, and then variations to allow for background images and css – such as supersleight and Angus Turnbull’s png fix – appeared as web 2.0 took off and we started to make more handsome and detailed web pages.

A recent discussion with a work collegue highlighted one major flaw with this approach – the alpha image loader does not support background-position – and as every decent front-end developer knows, you can’t sprite images without this bit of handy css. I’ve also recently discovered that according to Stoyan Stefanov at Yahoo!, the alpha image loader is in fact also very bad for performance.

With this issue in mind, I came across a different technique for loading alpha png images in IE6. Drew Diller’s technique loads a VML element into the DOM which can then be styled using a full alpha .png. It also appears to be faster than the alpha image loader – though if the browser doesn’t have access to javascript then the alpha image loader would appear to be the only option.

With IE6 usage down to as little as < 5%, perhaps we don't have to wait much longer to leave these dirty little hacks behind us.

Transparent .png images in IE6

A jQuery function that performs an .each in reverse

Sometimes you need to start at the end of a set of selected items. The .each function runs a function starting from the beginning, but theres nothing similar to loop backwards. The reverse selector function does just that.

jQuery.fn.reverse = function(fn) {

   var i = this.length;

   while(i) {
        i--;
        fn.call(this[i], i, this[i])
   }
};

Usage:

$('#product-panel > div').reverse(function(i, e) {
    alert(i);
    alert(e);
});
A jQuery function that performs an .each in reverse

Performance: packing or minifying your javascript?

One thing I love about writing jQuery plug-ins is that every line of code counts towards performance. Its like real programming again. There are lots of difference ways in which you can improve performance but one must have is reducing the size of the JavaScript that comes down the wire from the server.

There are two options to use when reducing JavaScript file size – packing and minifying. Packing uses a compression algorithm such as gzip to physical compress the file to it’s smallest possible size, whilst a decent minifyer removes whitespace, renames variables and internal functions and removes unreachable code.

A while ago I came across this post by John Resig pointing out that although packing reduces the file size, it takes longer to ultimately execute, due to the repeated unpacking process every time the script is used.

After reading this I started using the Yahoo YUI Compressor to minify all of my plug-ins, and it worked well, typically reducing file sizes by 70% or more. Looking through the jQuery 1.4 release notes I noticed that the jQuery team have switched to Google Closure Compiler. This really is a great tool because the code is compiled and rewritten, instead of just applying a regex filter. You can use in in your build process as a Java jar, or online using the Closure Compiler Service. In tests I have been getting a consistently higher compression ratio with Google Closure, and the added benefit that I know the code is syntactically correct.

Performance: packing or minifying your javascript?

How to avoid the “A script on this page is causing Internet Explorer to run slowly.” message

Whilst writing a jQuery spell-checking plug-in, I came across an interesting problem with long running JavaScript code – the browser would timeout and display a message box to the user with the text “A script on this page is causing Internet Explorer to run slowly.” Even worse, the dialog gives the user the option to cancel the script, potentially breaking your page.

The solution was to use a timer to simulate a background thread, but the solution wasn’t generic and felt far from elegant. This week, with the approval of Google’s Distributed MapReduce patent, I realised that a simpler non-distributed map reduce algorithm would enable the running of code both asynchronously and over long periods of time in JavaScript.

Map reduce works by taking key/value pairs and running them through a function to create intermediate key/value pairs until all the data has been processed (map). The data is then filtered (reduced) to obtain a result. Joel Spolsky (Joel on Software) has a nice article that explains the fundamentals behind map reduce.

Sieve of Eratosthenes Example

The Sieve of Eratosthenes is an algorithm for finding prime numbers, this Wikipedia article has a  visual explanation of how it works. Its a great example of something that is processor intensive but can be broken up into smaller steps.

A standard JavaScript implementation (using Euler’s optimisation) would look something like this:


function eratosthenesSieve(upperBound) {

   var upperBoundSquareRoot = Math.floor(Math.sqrt(upperBound), 0);
   var isComposite = [];

   for (var m = 2; m <= upperBoundSquareRoot; m++) {

      if (!isComposite[m]) {

         _primes.push(m);

         for(var k = m * m; k <= upperBound; k += m) {
            isComposite[k] = true;
         }
      }
   }

   for(m = upperBoundSquareRoot; m <= upperBound; m++) {
      if (!isComposite[m]) primes.push(m);
   }
}

The isComposite array contains boolean values indicating whether the interger is prime (false) or not (true). The primes array also contains the prime numbers that have been found.

Redefining the problem as a set of Map / Reduce functions

The great thing about map/reduce is that once the problem is defined as a set of functions, it doesn’t matter how the map/reduce is implemented, you should always get the same results. Usually, each for loop will result in a matching map or reducefunction. Reorganising the eratosthenesSieve function to use map reduce requires the following steps :

  • Map an array containing the initial values – in this case the index of the array is the number we are testing, and a boolean will indicate whether it is a prime or composite number.
  • Map each prime up to the square root of the upper bound. For each Map that is a prime, strike out it’s square multiplied by the remaining numbers until the upper bound is reached.
  • Reduce the array by totalling the number of primes (false values) left.
  • Execute the functions to return the result.

The refactored code now looks like this, using the fn.map and fn.reduce functions from the Leaf Javascript Framework:


//Updated function using theoretical fn.map and fn.reduce functions
function eratosthenesSieve2(upperBound) {

   //Create an array of booleans representing prime = false
   var composites = new Array(upperBound);

   //Set all to prime (false) to start
   fn.map(composites, function(index, value) {
      return false;
   });

   //Calculate the sqr root of the upper bound
   var upperBoundSquareRoot = Math.floor(Math.sqrt(upperBound), 0);

   //For each item, calculate the non primes
   fn.map(composites, function(index, value) {

      if (index  upperBoundSquareRoot) return value;

      //If the array item is a prime then map all non primes
      if (value == false) {

         var k = index * index;

         fn.map(composites, function(index2, value2) {

            if (index2 == k) {

               k += index;
               return true;
            }
            return value2;
         });
      }
      return value;
   });
                
   //Count only the primes
   fn.reduce(composites, 0, function(index, value, result) {

      if (index >= 2 && value == false) result++;
      return result;
   });

   return fn.execute();
}

The first fn.map function initialises the composites array. The second and third map fn.map strikes out multiples of primes. The fn.reduce function counts the remaining primes by accumulating the result variable. Note the extra work we have to do to simulate the functionality of the for loop and when we haven’t performed any processing we return the same value that was passed into the function.

Finally, we fn.execute the functions. If you attach a debugger to the script, you’ll notice the functions only start executing once this method is called. A map or reduce functions is executed on each tick of the timer, and in this way any arbitrary code formulated in this way can run in the background of a browser without causing the script timeout message to appear.

You can get an actual implementation of these functions in the Superset JavaScript framework on GitHub.

How to avoid the “A script on this page is causing Internet Explorer to run slowly.” message