Wednesday, January 20, 2010

The Joy of Javascript

The Joy of Javascript

or... the joy of ECMAscript or Standard ECMA-262 Script

I may have realised I really liked javascript before I started reading him, but it was only after I found Douglas Crockford's articles on the subject that things perhaps crystallized.

I can sum up the point of my blog post here by quoting from one of Douglas Crockford's articles:

"... JavaScript has closures. What this means is that an inner function always has access to the vars and parameters of its outer function, even after the outer function has returned. This is an extremely powerful property of the language. There is no book currently available on JavaScript programming that shows how to exploit it. Most don't even mention it."

-- Douglas Crockford From: http://www.crockford.com/javascript/private.html

This was written many whiles ago, so it's quite possible that there are books that talk about this now - I don't know for sure...

Before I get back to the closure, I'm going to reel off some of the things I like about javascript.

[0] Has the basics

A good scripting language should make it easy for you to wield both normal index arrays and associative arrays (hashes, dictionaries or whatever you want to call it). You can do a lot with just these 2 datastructures. It's the bread and butter of scripting.

Array behaviour:

  var ar = [];
  ar.push(1);
  ar.push('foo');

Associative array behaviour:

  var assoc = {};
  assoc['foo'] = 'bar';

Javascript's associative array ({}) is also it's basic object which you can easily modify...

[1] Simple Objects - can be handy

A simple javascript object is easy as:

  var obj = {};

This is the same as its associative array. And you can add to it like this:

  obj.param1 = 'some parameter';

This is the object-style of adding and amending simple objects in javascript, using the dot operator.

This form is the same as

  obj['param1'] = 'some parameter';

which is the associative array format. Here is yet another way using object literals:

  var obj = { param1: 'some parameter' };

Nice, light-weight, easy. No fuss. It's an easy way to bundle some things together quickly.

[2] Simplicity and consistency

Javascript (ECMA-262) is a one-trick pony. All it's goodness is built around one simple thing: the closure. In fact, pretty much everything else it has is fairly ordinary or lacking.

Some languages have a feeling of more consistency than others. On the "consistent" side we have languages like ruby/smalltalk ("everything is an object"), lisp (no syntax, macros and lexical closures, "everything is a list" ), haskell (pure/functional), javascript ("the closure, stupid!") etc etc and on the other we have: perl, php and maybe languages like visual basic 6 which feel a bit cobbled together or perhaps lack magic or have too much crudely bolted on in some unexpected, hard-to-read way.

So, what is javascript's one trick... Javascript has closures and variables; a root Object and a prototype system if you care to use it.

Behold the closure

  var F = function() {}

That's it.

You can call it:

  var f = F();

Closure as object

If you call F and it returns something that lives on in your program and that refers to something defined locally inside of F(), then you have a closure. It's kind of like a forerunner to an object instance (as recognised by a java or ruby programmer) because some state and functionality lives on specific to that particular invocation of F().

Here's a little pattern for creating object-like entities (I might also refer to these as quasi-objects).

  var F = function() {
    me = {};
    var secret = 1;
    me.public_property = 2;
    me.privileged_func = function() {
      return secret;
    }
    return me;
  }
  var f = F();
  f.privileged_func();

privileged_func is privileged because it has access to the secret variable.

Every time we make a new f, a new copy of privileged_func will be created. This isn't necessarily a problem but if want to optimise, and your objects you can add functions outside of the closure created by F().

  F.methods = {
     func1:functions() { return this.public_property; },
     func2:functions() {....}
  }
  F.make = function() {
    var n;
    var f = F();
    for(n in F.methods) f[n] = F.methods[n];
    return f;
  }
  f = F.make();

Here we introduce F.make which does the job of adding in public functions to an instance of F(). Note that these public functions can refer to the object they have been assigned to via the this keyword. Above, func1, accesses the public_property of an instance of F.

Javascript also allows you to instantiate objects using the new keyword. This creates object instances (in which case F is referred to as a constructor and f as an 'object instance' often shortened to 'object'). Instantiating with the new keyword tells javascript to create an object that uses javascript's prototype system.

  var f = new F();

Note that the function defined inside F will not be available. A privileged function pattern for object instances is shown near the end of this article.

Whether you work with F either calling it directly or with the 'new' operator, you are still working with the same thing, that works the same way: the closure.

And that's it. This is what makes javascript simple and sort of consistent (to use this term very loosely): the closure, the most protean thing known to computer science.

[3] Prototypically Overrated

It seems that javascript's coolness is often touted along the lines of its prototype system or alternatively, that it can be made to mimic classically object oriented programming languages.

Prototypes allow you to share functions across multiple instances. We did this manually in the above example using F.make(). If you use the 'new' operator, you get this for free via javascript's prototype system.

Prototypes are a good way to conserve memory and define functions that get shared by all object instances created from a constructor similar to F.make().

But prototypes are limited in the same way the F.make() strategy is limited.

If those methods you add to the prototype need to access the state of the object instance, that state will need to be publicly available.

Prototypes and inheritance (prototype or classical)

My preference when writing a complex system of objects and functions, is to hide all but the methods that an object is prepared to expose to the world outside of it. Everything else should be hidden using javascript's closures.

Not doing this is like asking your object to wear all it's innards and internal organs on the outside for all to see and run amok with as they choose.

Minimizing and making explicit the interface your objects, quasi-objects and modules provide to the outside world, helps you to more easily reason through your code and the systems you construct with those objects and modules. And it allows you to more easily re-implement an object whilst maintaing its interface to said world. (If you are wondering what is meant by "modules", this is covered further down.)

You solve exposed state problem by not using prototypes and instead adopting a privileged function pattern.

The prototype chain (prototype inheritance) is also touted as a benefit; as javascript's version of classical inheritance. Whilst this is useful, for code reuse (where you specialise an existing object to solve a new problem), and for things like convenience wrapper functions, overuse of inheritance (prototype or classical) can make your code harder to read and reason through.

You not only have to think "horizontally" about the interfaces that your objects and modules expose and how they are used; but you also have to think "vertically" up a class or object hierarchy.

Prototypes encourage you not to hide state and to potentially build "vertical" hierarchies.

Prototype example

  • Here's a basic prototype example where we set an object 'proto' which contains some useful methods as the prototype for the F constructor.
  • privval is not accessible by F's prototype object F.prototype
  • Only values defined through the this keyword in the F constructor will be accessible to the functions defined in F.prototype.
  • These values are publicly available to anything that can see or access an instance of F. So we can't hide the state.
  • If you replace the anonymous object literal assigned to F.prototype with an object instance of another constructor (say g = new G()), you can start to build a chain of prototypes. The methods in G.prototype will be available to both f and g.


  var F,f;

  // Constructor F:
  F = function() {
    var privval = 1;
    this.pubval = 'mess with me!';
  }
  F.prototype = {
    meth1: function() { return this.pubval; }
  }
  f = new F();
  f.meth1(); // returns this.pubval
  f.pubval = "here's a change!";


Maker function pattern to the rescue

This article appears to be suggesting that - through an extra closure - we can encapsulate an object's state and still use a prototype to access it. Basically, we use a closure courtesy of calling a maker function, to encapsulate the two. I'm not entirely sure at this point how it would be done.

[4] Half-way functional

Javascript sits between functional and object oriented programming worlds. You can whip up anonymous functions and pass them around with gay abandon. This type of thing can lead to patterns and techniques that allow you to do powerful things. If you understand the concept behind closures you'll start to get the hang of it and you won't look back.

Closure gotchas

It can also get a little confusing. If an outer closure has a variable that changes - say in a for-loop - and during each iteration of the for-loop you generate a new inner function (not closure) that will get executed later (eg as an event handler) and which refers to something that changes with the for-loop (eg the looping variable), you'll find all your inner functions will refer to last item in the for-loop. Unfortunately, you need to manufacture an inner closure and pass in the changing variable into it so that a copy is taken and stored in that closure. This inner closure returns the inner function which you can then use. This type of thing can get expensive too.

Here's an example:



var cf1 = [];
var cf2 = [];

function createFuncs1() {
  var i;
  for(i=0;i<10;i++) {
    cf1.push(function(){alert(i);});
      // GOTCHA: 'i' refers to whatever state
      // 'i' was left in the closure associated with
      // createFuncs1.
      // This will be 10.
  }
}

// Add a closure to solve the problem...

function createFuncs2() {
  var i;
  for(i=0;i<10;i++) {
    cf2.push(
      function(i2){
        return function(){alert(i2);};
      }(i)
      // i2 is a local variable of the inner closure
      // that is created with the invocation using 'i'.
    );
  }
}

createFuncs1();
cf1[0](); // 10
cf1[1](); // 10
createFuncs2();
cf2[0](); // 0
cf2[1](); // 1
cf2[2](); // 2


Similarly with objects. You can mimick some of the things that "real" OOP languages have if you really want to force it or you can use javascripts prototype system - see the links and discussion above.

[5] The module pattern (variation on yahoo pattern)

Modules created using the module pattern are invoked once (when your program is read in to the interpreter), returning an object that gives access to stuff living inside that closure. It can be pretty much anything too. You can use modules created by this pattern to store functions, variables and objects (both the constructors and object instances). You can make all of these public or keep them private. If you want your module to keep state like an object with some private variables, it can. If you want to stash some functions in a namespace, you can use a module to do that.

Here's one way to do it:


  var Module1 = function() {
    var module = {};
    var private1 = ... ;
    module.public_function1 = function() {
      ...
    }
    module.PublicObject1 = function() {
      ...
    }
    var private_function1 = function() {
      ...
    }
    function PrivateObject1 {
      ...
    }
    ...
    return module;
  }();

  // Later...

  var obj1 = new Module1.PublicObject1();
  var result = Module1.public_function1();
    // I'm adopting a rubyish convention of
    // camel-casing classes (constructors in
    // javascript speak) and underscoring other stuff.
    // Whatever floats your boat.


  • Module1 is a global variable which is assigned the result of function(){}()
  • local variable 'module' refers to an empty object ({}) which we proceed to fill
  • public functions and object constructors are added to module; you could of course add variables to module as well
  • private variables, functions and objects are created without being added to module; they stay hidden within the scope of Module1 closure
  • module is returned at the bottom to the outside world - in this case to the global Module1 variable (GOTCHA #1)
  • Don't forget to execute function(){...}() otherwise Module1 is just a refernce to the function itself (GOTCHA #2)

[6] The privileged function pattern

The term privileged comes from Douglas Crockford who clearly demonstrated it. The idea is that you can create private state in your object instances by using local variables inside the constructor.

A privilege function example was shown near the beginning of this article using f where f = F(). The example below is one way to use this pattern for instantiated javascript objects.

By adding a function to the this variable inside the constructor (or, in the example below I've assigned this to me and used this instead), this function, which acts like a public method, gets access to these local variables which would otherwise not be accessible (when you instantiate an object instance). In the example below, accessor1 is an example of a privileged function which can access local variables priv1 and my in the closure formed by an instance of Object1:


  var Object1 = function() {
    var me = this;
    var priv1 = 'priv1';
    var my = {}; 
      // Private state.  You don't have to do this.
      // Just define functions and variables as normal
      // if you prefer.

    me.accessor1 = function() {
      ...
      // accessor1 is a public method but can also
      // access 'priv1' and 'my' above.
    }
      // You can also say 'this.accessor1 = ... '

    my.init = function() {
      ...
    }

    my.init();

  }

  // Create an instance of Object1.
  var obj = new Object1();
  var result = obj.accessor1();


  • accessor1 can see everything inside the of function() that is referenced by Object1.
  • me is a reference to the object (this); there are potentially siuations where this can change so we stash it in me and use me ever after; you can probably get by with this in many cases if you prefer
  • the use of my is not part of the pattern; it is something I often do to distinguish from me for private stuff that the outside world cannot see. Matter of taste. You could just use something like the priv1 variable.
  • the init() function is not part of the pattern, but demonstrates defining and using a private function in this case to group all the initialisation instructions together to run at the end of the constructor when you instantiate an instance of the object.

Concluding Remarks

Judicious use of javascript's closures gives you surprising scope to build complex applications. Using the module pattern and privileged functions and closures in general you have plenty of scope to build complex behaviour within the browser and on the server using frameworks like rhino.

There's plenty of scope here to talk about conventions - how to organise and package code often using the above two patterns. I have written a standard that tries to set this out which I might revisit. You can find it here: http://js.web17.com.au/specs/packaging-and-namespacing/index.xhtml

You can find some of my javascript code at: http://github.com/danielbush

No comments: