LA.NET [EN]

Sep 22

Oh damn! Can’t you see that’s a constructor?

Posted in Javascript      Comments Off on Oh damn! Can’t you see that’s a constructor?

Even though I’ve been in Silverlight/C#/WCF land in these last months, the truth is that I’ve always been a JavaScript aficionado. In fact, if you’ve been reading my blog, you’ll probably recall a small series I’ve done on it a few months ago(if not, then don’t worry: you can still read it here). After speaking with a friend today, I think I might have missed a cool advice on how to define constructors in JavaScript.

As we all know, JavaScript OO programming is a little different from what we’re used to in traditional languages like C# or Java. You see, you can’t really reuse the same style of programming because things work in a completely different way in JavaScript land. Anyway, I still believe that it’s one of the coolest, more flexible languages you can use  (provided you don’t try to write JavaScript a la C# or Java). I’m not really getting into details here, but there are times where you want to create a constructor. oh, and yes,in JavaScript a function can be a constructor. And this is where problems might occur. Let’s start with a simple example:

var Point = function (x,y) {
    this.x = x;
    this.y = y;
}

var pt = new Point(1, 1); //correct usage
var anotherPt = Point(1, 1);//hum…not the intended usage

Ok, so can you see what’s happening here? Btw, before you start laughing, I’ve seen this happen  in the past (yes, in the real world!). When Point was created, it was meant to be used as constructor. But that doesn’t mean that a rookie or someone who is not paying attention can’t  call the Point function directly without using the new instruction. When that happens, the this special variable won’t point to a Point instance. In this case, it was probably referencing the window object, but it all depends on the existing context at time of invocation.

Now, if you’re writing frameworks, this is really a nightmare. You need to have some way of not allowing this. The good news is that there’s a way to fix this and it involves using the instanceof operator in 2 or 3 lines of code. Take a look at the next snippet:

var Point = function (x, y) {
    if (!(this instanceof Point)) {
        return new Point(x, y);
    }
    this.x = x;
    this.y = y;
}

And that’s it! really! When the function is invoked, we start by checking if this points to an instance of Point. When you use new, this does reference a Point instance. However, that doesn’t happen when you call the Point function as a function. With this small change, you’re ensuring that you’ll always get a new initialized Point instance from that method. Wasn’t that easy enough? And that’s it for now. Stay tuned for more.