Please visit my new campsite listing site ukcampingmap.co.uk


Archive for November, 2009

This literally changes

Monday, November 30th, 2009

You should know that I’ve built up a lot of half-written posts recently, mostly about javascript, so this blog, as it emerges from semi-hibernation, is gonna get code-ier and more out of date as I work backwards.

So to begin at the end, I recently came across a bug which is far from obvious to track down. Look at the code below.

var MyClass = function() {
  this.a = 'dolphin';
  this.getA = function() {
    return this.a;
  }
}

myObject = new MyClass();
var callbacks = {callback1: myObject.getA}
newA = callbacks.callback1();

What will the value of newA be?

In my application, in which I used callbacks to store the callback functions for a series of custom-made dialog boxes, I was expecting the value to be a, but it isn’t. The reason for this is that callbacks is an object, and saving a function as a property of an object is, in effect, creating a method of that object, and methods of objects, when called using the ‘.’ syntax, will tend to have this refer to the object (not always, but normally). So in creating the callbacks object you inadvertently cause getA to fail as this no longer points to the myObject object, but to the callbacks object literal.

Fair enough. But what makes this error particularly difficult to track down is that firebug shows console.log(callbacks) to be an empty object. Why this is, I don’t know – it seems unlikely to me that the properties wouldn’t be created due to the value of this being reassigned, so maybe it’s a mistake in firebug ( a firebug-bug, if you will). A similar error occurs when using an array as callbacks instead of an object, but firebug reports that the function is stored in the array, and that it returns an undefined value, so it’s a lot easier to see what the problem is. But once the bug is found, the workaround for the array and the object is the same.

The method I’ve chosen is to define

var that = this;

at the top of the MyClass function, and anytime you use this but think it may be called in such a way that the context may change, substitute that for this. But this is far from perfect – you have to second guess when you will need to do this as it’s not always obvious, and you could easily miss an instance which doesn’t occur very often, but which is fatal when it does. Another solution is to use the prototype.apply method to explicitly set the context of the method, though it looks ugly and a bit indecipherable. On the other hand it is a lot more bulletproof.

I’m sure you’ll make the right decision.

(More sponge creature fun here)

Curly-haired children

Sunday, November 29th, 2009

Clarkson! Colonise!It’s not every day you hit a refresh button and are faced with what looks like a Daily Mail plot to finally rid the world of sympathy for windfarms.

But quaking in fear aside, You’ll notice that I spelt colonise the British way… but the site still let me in though, which is awfully nice/stupid of stackoverflow. Hip hip…

But it works for me!!!

Monday, November 16th, 2009

The lines of javascript below, included at the top of your scripts, could save you a lifetime of confusing conversations with clients where they say an application doesn’t work and you can clearly see that it works on your laptop.

The difference is that you have firebug installed and they don’t, so for you console is defined, but for them it is not, so if you leave any references to it in the app it will throw an error for them. But this fixes that;

if(!console) {
 var console = {};
 console.log = function() {
   return null;
 };
}