Monday, February 16, 2009

Javascript Constructors

Javascript has a problem with constructors.


function Thing () {
this.foo="bar";a
this.bar="baz";
}


this is okay if you call Thing as
var thing = new Thing();

That creates a new object, whose prototype is Thing.prototype, and binds that object to "this", and then executes the Thing function.

However, if you do this:
var thing = Thing();


"this" instead gets bound to the global object, and you end up with the global variables "foo" and "bar".

Douglas Crockford concieved a function named "object", that will be baked into the next version of the ecmascript standard. (as a static method named "Object.create" )

The object function takes an object as a parameter, and creates a new object whose prototype is the given object, and simply returns it. The implementation goes like this:

function object (o) {
var f = function () {};
f.prototype = o;
return new f();
}

you can use this to create safer constructor functions.

function Thing () {
var that = object(Thing.prototype);
that.foo="bar";
that.bar="baz";
return that;
}

Now, this function does exactly the same as the above Thing function when you call it like this.

var thing = new Thing();


but when you forget the "new" keyword

var thing = Thing();


it still does exactly the same, avoiding global namespace pollution.