Saturday, 29 March 2008

What's in a name?

Micro-post today, folks:

You see a fair bit of confusion from newbies in mailing lists around the "name" attribute vs. the "id" attribute. (Edit 21 March 2010: Confusion not helped by a bug in Internet Explorer; more here.) For instance, I recently saw a "how do I do this" -style post asking how to deal with a form, with the sample being:

<form name='form1'>
<label><input type='checkbox' id='cb1'> Checkbox 1</label>
</form>
The poster wanted to know how to retrieve the form and submit it (along with some further information) via Prototype's Ajax.Updater. So he wanted to use the serialize() method Prototype adds to form elements when it extends them (e.g., when you retrieve the element using $()).

Consequently, the use of "id" and "name" attributes in his example was exactly backward: He wanted to be able to retrieve the form using $(), which is a general-purpose routine that retrieves elements by their unique ID, and then have the form fields submitted -- but the form field had no name.

Here's the mantra:
Elements have IDs; form fields have names.
IDs are unique in the document; form field names are not (necessarily).

Two further notes:

1. Form fields can also have IDs if you need to refer to their elements in your code (to enable/disable them, etc.), but in terms of sending in a form, fields have names.

2. You don't have to use an ID to get at the element for a form; you can use a name and then get at the form element via document.YourFormName in your JavaScript code. But nowadays we mostly look elements up by their unique IDs; and in the specific case of the question from the poster above, since he was going to want to use $(), he would want an ID.

Monday, 24 March 2008

Mythical methods

Note: As of ES2015, JavaScript arguably got methods (and that is the term the spec uses) via a new notation on object initializers and via the class syntax. This article predates ES2015 and refers to non-method properties on prototypes, created with the function keyword (the new method syntax doesn't use the function keyword).
We frequently talk about JavaScript objects having methods. This is just a convenient myth. JavaScript has functions, but it doesn't have methods. It doesn't need them. Its functions, combined with some syntactic sugar, are more than up to the job.

What is a "method"? I'd have to say that the definition given on Wikipedia is pretty good. As of this writing, it says a method is
...a subroutine that is exclusively associated either with a class...or with an object...
Yeah, JavaScript doesn't have any of those. Granted it seems to have them. For example:
function Guess(killer, location, weapon)
{
    this.killer = killer;
    this.location = location;
    this.weapon = weapon;
}
Guess.prototype.accuse = function()
{
    alert('It was ' + this.killer +
          ' in the ' + this.location +
          ' with the ' + this.weapon +
          '!');
};

function testGuess()
{
    var mustardStudyLeadPipe;
    var plumHallRope;

    mustardStudyLeadPipe = new Guess(
        'Colonel Mustard',
        'study',
        'lead pipe');
    mustardStudyLeadPipe.accuse();

    plumHallRope = new Guess(
        'Professor Plum',
        'hall',
        'rope');
    plumHallRope.accuse();
}
Running testGuess does indeed show us
"It was Colonel Mustard in study with the lead pipe!"
and then
"It was Professor Plum in hall with the rope!"
so that looks an awful lot like accuse is a method of Guess objects.

Except it isn't. Let's add a bit to our testGuess function (new bits in bold):
function testGuess()
{
    var mustardStudyLeadPipe;
    var plumHallRope;
    var accuse;

    mustardStudyLeadPipe = new Guess(
        'Colonel Mustard',
        'study',
        'lead pipe');
    mustardStudyLeadPipe.accuse();

    plumHallRope = new Guess(
        'Professor Plum',
        'hall',
        'rope');
    plumHallRope.accuse();

    accuse = mustardStudyLeadPipe.accuse;
    accuse();
}
What does the final call to accuse show? Does it accuse Colonel Mustard? No, all we've done is get a reference to the accuse function into our local variable, there's nothing there (or in the function definition) that refers to the mustardStudyLeadPipe instance or indeed anything related to Guess. No, what this shows will depend on the HTML document in which it's found, but it'll be something along these lines:
"It was undefined in the http://blog.niftysnippets.org with the undefined!"
Why? Because we didn't do anything to define "this" within the function. (I'll come back to details on why we'd get seemingly-odd alert that includes a URL in a bit.)

There are three main things about JavaScript that make it seem to have methods (leaving aside prototypes and "classes" for the moment): The "this" keyword, the fact that object properties can refer to functions (since they are, after all, just objects), and the fact that when you call a function using an expression that gets the function reference from an object property (e.g., object.functionName() or object['functionName']()), the object is set automatically as "this" within the function call.

Let's look at each of those.

The "this" keyword: This keyword looks familiar if you're coming to JavaScript from a background in C++, Java, C#, and the like, where "this" within a method is guaranteed to refer to an instance of the class defining the method (or a subclass). And in JavaScript, "this" does refer to an object instance, but that's where the similarity ends. Other than the name being the same and it referencing an object, it bears no relation to the "this" keyword in class-based languages like C++, Java, or C#. In fact, in many ways, "this" is actually just a function argument that is supplied in a non-obvious (but convenient!) way.

Functions as properties: Let's look again at one line from the code above:
mustardStudyLeadPipe.accuse();
If we were talking about that line of code, we'd probably say "...the accuse method of the mustardStudyLeadPipe object...", which is a useful and convenient way to put it. A more painstakingly-geeky-accurate way of putting it, though, would be "...the function referenced by the accuse property of the mustardStudyLeadPipe object..." Not that anyone's going to say that, but that's really what's going on. Objects don't have methods, they have properties; it's just that a property can refer to a function, since functions are objects like everything else.

Functions called via property references get "this" set for them: This is the part that really makes it seem like JavaScript has methods: The "this" reference gets set automagically to the object instance if you call a function via a property reference. Let's look at that call again:
mustardStudyLeadPipe.accuse();
This does three completely distinct things: Firstly, it identifies a function to call by getting the function reference from an object property; secondly, it says to call the function and return its result rather than just get a reference to it (the parentheses do that); and thirdly, it says that within that call, use the object in question as "this". These completely distinct things are combined in that notation for our convenience. Getting the function reference from an object property doesn't link it in any way to the object the property came from (as our accuse test above confirmed), it just gets a reference the function; the JavaScript engine treats calls of functions just retrieved from object properties as special and sets up "this" accordingly, but it has nothing to do with the function being called.

Lets prove that another way:
function testGuess2()
{
    var plumHallRope;
    var fakeGuess;

    plumHallRope = new Guess(
        'Professor Plum',
        'hall',
        'rope');
    plumHallRope.accuse();

    fakeGuess = {};
    fakeGuess.location = 'library';
    fakeGuess.killer = 'Mrs. Peacock';
    fakeGuess.weapon = 'revolver';
    fakeGuess.demo = plumHallRope.accuse;
    fakeGuess.demo();
}
This accuses Professor Plum as before, and then:
"It was Mrs. Peacock in the library with the revolver!"
The exact same function produces the alerts in both cases, it's purely the way it was called that defined "this". The fakeGuess object isn't even really a Guess -- "fakeGuess instanceof Guess" returns false -- but it has all of the properties the function expects (killer, location, weapon), and so it works just fine (this is something we'll come back to in a later post). Essentially, "this" is just a function argument that's passed into the function as an implicit feature of calling a function via a property reference.

We can also do it explicitly. JavaScript gives us the call and apply methods on function instances, with which we can say explicitly what we want "this" to be. (They do the same thing, they just provide different ways to specify the function's arguments.) If you say myfunction.call(myobject), you're saying "call myfunction and use myobject as 'this'", which is what the property-retrieval stuff does implicitly for you. In fact, this:
plumHallRope.accuse();
equates to
plumHallRope.accuse.call(plumHallRope);
Now all three of the parts we identified above are shown distinctly: Getting the function reference from the property (plumHallRope.accuse) is distinct from the fact we're calling it (call) is distinct from what "this" should be ((plumHallRope)). The fact that these are distinct can be made clearer:
var f;
f = plumHallRope.accuse;
f.call(plumHallRope);
Alternately, here's a more dramatic example:
function testGuess3()
{
    var plumHallRope;
    var fakeGuess;

    plumHallRope = new Guess(
        'Professor Plum',
        'hall',
        'rope');
    plumHallRope.accuse();

    fakeGuess = {};
    fakeGuess.location = 'library';
    fakeGuess.killer = 'Mrs. Peacock';
    fakeGuess.weapon = 'revolver';

    plumHallRope.accuse.call(fakeGuess);
}
Not to bang on about it, but the call at the end accuses Mrs. Peacock, not Professor Plum. The plumHallRope instance was only used to get the function reference, it wasn't used within the function call. In our original testGuess function, we could even do this if we wanted to:
mustardStudyLeadPipe.accuse.call(plumHallRope);
Which accuses Professor Plum. But it's more convenient, isn't it, to say plumHallRope.accuse?

So if "this" is really just a sort of obscure function argument, why have it? Why not just write everything as global functions and pass in the object to act on as the first argument? We could do that (and in fact I did it for years, as a C programmer), but it's more cumbersome. You have to know what functions are meant to be used with what kinds of objects, there's all sorts of stuff littering up the global namespace, etc., etc. By passing around object references, which have properties on them (usually inherited from their prototype; again the topic of an upcoming post) that reference functions intended for use with them, it's just so much more convenient.

Okay, but what was that about that URL showing up earlier when we called accuse? You'll remember earlier when we ran this code:
    accuse = mustardStudyLeadPipe.accuse;
    accuse();
we got the alert with the URL in it. So why did that happen, and where did the URL come from? It was because we didn't give an object to use for "this", and so the function call got the default, which is the JavaScript global object. In browser implementations, the global object is the window object -- so we were showing the values of window.killer, window.location, and window.weapon. In a typical situation, window.killer and window.weapon will be undefined, and of course window.location is the URL of the document in the window.

I chose that example intentionally, because it's a pitfall people fall into a lot: Losing "this". Usually, people lose "this" in the context of an event handler -- e.g., they have an instance (plumHallRope, perhaps), and want to hook up a "method" on it (say, accuse) to an event (a click handler for a button, maybe?), and so understandably they do something like this (I'm again using convenience syntax, as I describe here):
Event.observe('theButton', plumHallRope.accuse); // WRONG
The problem being, that just references the function, nothing about its context. Its context will be determined by how it's called. Earlier when we called accuse directly, because we didn't do that via property retrieval or call or apply, "this" was the global object; event handlers like this one will usually get "this" set to the element (although not if you're using old DOM0 -- onclick attribute -- events or IE's attachEvent function). To maintain its context, you have to do something like this:
Event.observe('theButton', function() { plumHallRope.accuse(); });
The function that gets called by the event handler then turns around and calls the accuse function such that plumHallRope is "this", so you've preserved "this" using a wrapper (which is also a closure; details). (Note that thanks to a bug in Internet Explorer, that may well cause a memory leak for your IE users. Prototype's Event.observe() does some things to minimize the issue; other frameworks will have other helpers along those lines.)

In Conclusion:

I've seen people deride JavaScript for having "fake" methods, but I think that's missing the point. It doesn't have fake methods, it just doesn't have methods at all. What it does have is very powerful, flexible functions and some convenient syntactic sugar that lets us express the 90% case -- calling a function related to an object instance passing in that object instance as an argument -- in a compact and expressive way, but without limiting our use of the functions involved. By not limiting our use, we can use just about anything as a mixin, we can use duck typing, easily create wrapper objects to enforce or verify contracts, etc.

Like so many things about the language, it's confusing until you grok just how simple it is, and then you start appreciating that it's simple but powerful.

Convenience Syntax in Examples

This is a "meta" post, e.g., it's about the blog itself.

In many of my posts, I give code examples to illustrate a point. To avoid cluttering the examples up with browser-specific stuff, I'm using a couple of calls from the Prototype library.

Actually, right now, just the one: Event.observe(). This function hooks up an event handler in a way that is consistent across browsers, even Internet Explorer, which is good because IE doesn't support the standard addEventListener() function, and its own attachEvent() function behaves slightly differently (within the handler, "this" is the global object, like in old DOM0 handlers; whereas with addEventListener it's the element you're hooking the event to). Prototype's Event.observe() ensures that "this" is always the element, even on IE, and also does some housekeeping to try to mitigate an IE bug where it tends to leak memory if you use closures as event handlers (which is incredibly common).

If I use more Prototype stuff, I'll list it here as well, but this is only about trying to keep the examples simple and clear, not about using Prototype or any other specific library...

Tuesday, 18 March 2008

The Horror of Implicit Globals

This code should cause an error, right?

function doSomething()
{
var x;

x = 10;
y = 20;

alert('x = ' + x);
alert('y = ' + y);
}
Well, you'd think so, wouldn't you? (There's no declaration for y.) It doesn't, though. It also probably doesn't do what the author intended. Welcome to The Horror of Implicit Globals. The good news is that there's something we can do about it.

Update 2010/03/31: Please see the update at the end of the article, there's good news on this front.
So what did the code really do? Well, in a simple test, it would seem to do what the author intended, in that it shows two alerts:
  • x = 10
  • y = 20
But x and y are completely different; x is a local variable within the function, whereas y is created as a "global variable". Said "global variable" is not declared anywhere at all, it exists purely because it was assigned to by this function. Functions can create global variables willy-nilly with no advance declaration or indeed, with no declaration at all.

This is clearly a Bad Thing, so why would the language designers let it happen? Well, in some sense I think it's a side-effect. To see why we have the possibility of implicit globals, we have to delve into objects and properties.

If you've done any JavaScript stuff with objects, you know that you can assign a property to an object simply by, well, assigning it:
myobject.myprop = 5;
This sets the property myprop on the object myobject, creating a new property if the property didn't exist before. This is simple, it's convenient, and it's part of the power of JavaScript that objects can just acquire properties without any preamble.

But what does this have to do with implicit global variables? Well, you see, JavaScript doesn't have global variables. No, seriously. It has a global object (just the one), and that object has properties. Those properties are what we think of as global (or page-scope) variables. You might think that this is a distinction without a difference, but if it were, the code shown at the beginning of this post would fail because y isn't declared. It doesn't fail, because by assigning y a value, we created a property on the global object.

"Now hang on," you're saying, "there's nothing in that code referencing some kind of 'global object'." Ah, but there is. And that brings us to the scope chain.

I've mentioned the scope chain before. The scope chain is how JavaScript resolves unqualified references: In any given execution context (e.g., global code or function), there is a chain of objects that the JavaScript engine looks to when resolving an unqualified reference: It first checks to see if the top object has a property with the given name, and uses that property if it does; if not, it checks the next object in the chain, etc. The global object is always the last object in the chain. If the engine gets all the way down to the global object and we're assigning a value to the unqualified reference, the reference is assigned as a property of the global object. And since properties don't have to be declared in advance, voilá, implicit globals.

We can see this in practice. The JavaScript specification says simply that there is a global object and that it's always the root of the scope chain, but it doesn't say what it is -- which makes sense as JavaScript is a general-purpose language. In browser-based implementations, though, the global object has a name: window. Technically, the symbol window in browser-based JavaScript is a property of the global object that refers to the object itself. I mention this not only because it's useful to know, but because it lets us prove to ourselves that "global variables" are really properties of the global object. Let's add a line to our code from above:
function doSomething()
{
var x;

x = 10;
y = 20;

alert('x = ' + x);
alert('y = ' + y);
alert('window.y = ' + window.y);
}
This starts out by showing the same two alerts we had before:
  • x = 10
  • y = 20
...and then it shows a third:
  • window.y = 20
...because y and window.y both refer to the same property of the same object, the global object.

All of this holds true even if we do declare y at global scope:
var y;
function doSomething()
{
var x;

x = 10;
y = 20;

alert('x = ' + x);
alert('y = ' + y);
alert('window.y = ' + window.y);
}
This shows the same three alerts shown earlier. (There is a very slight technical difference between declared and undeclared globals that relates to the delete statement, but the distinction isn't important here, it's just a flag on the property.)

Now, some readers will be thinking "Cool! This means I don't have to have 'var' statements for my globals! I can save a bit of space on the downloaded script files!" Well, true, you could. It's an awfully bad idea, though. Not only would it be a bit unfriendly to anyone else trying to read your script (I suppose you could address that somewhat with comments that get stripped out before download), but it would also mean you couldn't use any lint tools, and you really, really want to. Because the ramification of all of this is that a simple typo, perhaps:
thigny = 10;
instead of
thingy = 10;
can create a new global variable in your page, introducing a bug that's awfully hard to find. Fortunately, though, people have created various tools to do lint checking on JavaScript, tools that can find that error for you before you even get to the testing stage, much less production.

And so there we are, the horror of implicit globals -- and the relief of knowing that we have a defense against them!

Update 2010/03/31: Great news for anyone who's been hit by the Horror of Implicit Globals. The new ECMAScript 5th edition specification is out, and it introduces "strict mode." One of the (several) things strict mode does is prevent the very thing this article warns about: Implicit globals. If we were using strict mode, the function at the beginning of this page would have a syntax error rather than a very subtle bug. Result!

Monday, 17 March 2008

Now at blog.niftysnippets.org

Just briefly, this blog is now at http://blog.niftysnippets.org, rather than http://niftysnippets.blogspot.com. It's still hosted by Blogger (for now), and Blogger is kind enough to forward you from the old address, but if for some reason you're a regular reader of this blog, it's worth updating your Atom/RSS links just in case someday I end up hosting it myself or moving to Wordpress or something...

When you absolutely, positively need new scope

Just a quick one today, one that in many ways is a solution in search of a problem... ;-)

As you probably know, in most of the languages with vaguely C-like syntax (C, C++, Java, C#, ...), a new block introduces new scope. E.g., this Java code:

String myJavaMethod()
{
String s;

s = "outer string";

{
String s;

s = "inner string";

// (Presumably do something with 's' in here)
}

return s;
}
...while strange, is perfectly valid. It returns a String with the text "outer string". The s variable declared within the inner block is scoped only to the inner block.

A similar-looking JavaScript function has a completely different result:
function myJavaScriptMethod()
{
var s;

s = "outer string";

{
var s;

s = "inner string";

// (Presumably do something with 's' in here)
}

return s;
}
It's still valid, but it returns the string "inner string" rather than "outer string". Blocks do not introduce new scope in JavaScript, only functions do that. (If you're thinking that the second var declaration should be an error, well, I agree -- but it isn't, details here.)

But what if you absolutely, positively need new scope within a function? It's actually pretty easy to achieve; just use a closure. If I really needed my JavaScript function above to behave like the Java version, I could rewrite it like this:
function myJavaScriptMethodUpdated()
{
var s;

s = "outer string";

(function()
{
var s;

s = "inner string";

// (Presumably do something with 's' in here)
})();

return s;
}
Looks weird, eh? What I've done is create an anonymous inline function and then immediately execute it. Since it's a closure (all JavaScript functions are closures), it has access to all of the arguments and variables defined in its containing function except for the ones it's masked by declaring its own (which it's done with s).

Naturally, as this is defining and calling a function, there's a performance aspect although setting up a function call should be fairly quick in any decent JavaScript implementation -- and again, you're only doing this when you absolutely, positively need new scope, right?

So, okay, how is this useful? Well, as I say, this may well be a solution in search of a problem. It mostly gave me an excuse to highlight the fact that blocks don't introduce new scope in JavaScript. And frankly, in most cases if you need to set up new scope within a function like that, it probably means you haven't broken things up into small enough pieces; if you do that, you'll probably find that you don't absolutely, positively need new scope because your pieces are small enough that things are scoped properly.

That said, though, think in terms of sandboxing and namespacing -- if you wrap an entire external library in a closure and then execute that closure, any globally-declared vars in that library become local variables within the closure and can't conflict with others defined at global scope. So there may be something useful there, although it's far from a real sandboxing or namespacing solution...

Sunday, 16 March 2008

A simple point about design

A good friend of mine pointed me at this comic and I just had to share it. I've rarely seen this point put more...simply.

Saturday, 15 March 2008

Closures by example

In an earlier post, I promised a follow-up with a few examples of closures. Before we get to the examples, a quick note: To avoid cluttering things up with browser-specific stuff, I'm using the Event.observe() method from Prototype. Event.observe() hooks up an event handler, allowing for differences between browser implementations (see the link for more detail).

I have to say that I found this post to be a real challenge, and it took me a while to figure out why: I kept trying to boil things down to their essence, and the fact is that if you do that, you end up with a single example, one that demonstrates that a closure function has access to intrinsic data. And let's face it, that's not very interesting. :-)

So rather than boil things down, I'll give a few examples of where closures frequently get used, even though they all pretty much demonstrate the same fundamental point (about the functions having intrinsic data).

Okay, to the examples:

  1. A Simple Bound Event Handler
  2. Enduring References
  3. Enduring References to What
  4. Private Properties
  5. Callbacks
  6. The Inadvertent Closure (an anti-pattern)
  7. Your Examples
#1: A Simple Bound Event Handler

One of the most common uses of closures is to bind a function and some data to an event handler:
function wireUpMessage(element, msg)
{
Event.observe(
element,
'click',
function()
{
alert(msg);
}

);
}
This wireUpMessage function creates a closure (the bit in bold) and hooks it up to the "click" event of the given element, having it show the given message. The closure keeps a reference to the arguments and variables in scope where it was defined, so it has access to the msg argument we passed the wireUpMessage function, even though that function has returned.

Assuming we have a button with the ID "btnSayHey", we can use this as follows:
wireUpMessage('btnSayHey', 'Hey there');
Try it out:



#2: Enduring References

You could easily get the idea from the previous example that the closure we created somehow had the text "Hey there" bound into it literally. That's not true. It's the reference to the context containing the msg argument that's bound to the closure, not the value of that argument. The msg argument's value is evaluated when the closure is executed, not when it's defined. This is important, powerful, and frequently misunderstood. ;-)

Consider this:
function setupCounterButtons(startBtnName, showBtnName, stopBtnName)
{
var counter;
var intid;

counter = 0;
intid = undefined;

function startCounter()
{
stopCounter();
counter = 0;
intid = window.setInterval(function() { ++counter; }, 200);
}
function stopCounter()
{
if (intid !== undefined)
{
window.clearInterval(intid);
intid = undefined;
}
}
function showCounter()
{
var msg;

msg = "Counter = " + counter + " (";
if (intid === undefined)
{
msg += "not ";
}
msg += "running)";
alert(msg);
}

Event.observe(
document.getElementById(startBtnName),
'click',
startCounter
);
Event.observe(
document.getElementById(showBtnName),
'click',
showCounter
);
Event.observe(
document.getElementById(stopBtnName),
'click',
stopCounter
);
}
This function has the local variables counter and intid, three named functions (which are closures), and a fourth anonymous closure we've passed into window.setInterval. The named functions are: startCounter, which starts a 200ms repeating update of the counter local variable; showCounter, which displays the current counter value; and stopCounter, which stops the 200ms update. It hooks these functions up to the buttons whose names we pass into the function. So if we hook up the buttons 'btnStartCounter1', 'btnShowCounter1', 'btnStopCounter1' with this code:
setupCounterButtons('btnStartCounter1', 'btnShowCounter1', 'btnStopCounter1');
...we get to try it out:



This demonstrates two important things: Firstly, the closures have an ongoing reference to the counter variable, not its literal value where they're defined. Secondly, all of the closures are referencing the same context: When startCounter sets the counter and intid values, showCounter sees those changes; when the closure we've enabled via window.setInterval updates counter, we see that update. All closures defined in the same context share access to that same context.

#3: Enduring References to What?

Look again at the previous example and think for a moment about what it is that the closures have access to, which endures even after the setup function has completed. Is it something unique attached to the setup function? Well, if that were true, what would happen if I called the function again and hooked it up to different buttons; would those buttons control and access the same counter that the first set of buttons do? If your impulse is to say "yes," consider that counter is a local variable within the function. Local variables aren't specific to the function for all eternity, right? They only relate to a specific time you've called that function. So if we call it again...yup, that's it, we get a new context, and the closures within that context access that new context, not the previous one.

And so if we hook up a new set of buttons:
setupCounterButtons('btnStartCounter2', 'btnShowCounter2', 'btnStopCounter2');
We get a second counter. Try it out and see whether there's any interaction between the counter controlled by these buttons:



...and the one controlled by the buttons in the previous example.

Right, there isn't any, because they're referencing different counters.

#4: Private Properties

Lots of JavaScript apps these days make extensive use of object orientation. One key OOP principle is information hiding. There are several good reasons for information hiding. One example is to defend against an object instance having an invalid state. Frequently this is done by having private data members and only allowing access to them via accessor methods that can prevent invalid values. Since all properties of JavaScript objects are public, how can we have private data members? The answer, of course, is to use closures, much as we did with the counters above. (Crockford is probably the first to document how you can do this, here.)

Here's an example, a Circle class that ensures that its radius is never allowed to become negative:
function Circle(radius)
{
this.setRadius = function(r)
{
if (r < 0)
{
throw "Radius cannot be less than zero.";
}
radius = r;
};
this.getRadius = function()
{
return radius;
};

this.setRadius(radius);
}
Note that we don't have a "radius" property on this object at all. This code:
var c;
c = new Circle(10);
alert("Radius: " + c.radius); // undefined!!
Shows "Radius: undefined" because the property simply doesn't exist. Try it:



Instead, the setRadius and getRadius methods of the object are closures, both of which have a reference to the context in which they were defined, and they share that context as they were defined in the same scope. So rather than having a "radius" property, they simply use the radius parameter given to the constructor, which they keep a reference to even after the constructor has returned. Consequently, this code works just fine:
var c;
c = new Circle(10);
alert("Radius before update: " + c.getRadius());
c.setRadius(20);
alert("Radius after update: " + c.getRadius());
Try it:



(I should mention that there is a downside to this. When you do this, all Circle objects [for example] have their own copies of the setRadius and getRadius functions, rather than sharing copies on an underlying Circle.prototype object. That's a whole different topic, though.)

#5: Callbacks

Closures get used as callbacks a lot. Of course, event handlers are callbacks and so we've already talked about this, but it's useful to remember non-event-handler callbacks.

One very common example is container objects that offer a method (usually called "each" or "forEach") that will call a callback once for each contained object. Prototype provides this (Enumerable.each) on arrays and several other objects; Dojo has something similar (dojo.forEach); JavaScript 1.6 defines this for arrays (Array.forEach). So if we have an array (say) of Person objects, we can act on each element like this (using Prototype syntax):
personArray.each(
function(person)
{
// Do something with the 'person' object
}
);
Suppose we wanted to build a sublist of only the people who are 65 and over:
var sixtyFivePlus;
sixtyFivePlus = [];
personList.each(
function(person)
{
if (person.age >= 65)
{
sixtyFivePlus.push(person);
}
}
);
That uses a closure to add each 65-and-over person to the sixtyFivePlus array.

In practice, closures are used like this in modern JavaScript all over the place.

#6: The Inadvertent Closure (an anti-pattern)

In Example #1, I said that a very common use of closures was to bind a function and some data to an event handler. Unfortunately, while it may literally be true that that's a very common use, I suspect many times it's not the intent of the programmer creating the closure. I suspect much of the time, the programmer just wanted to bind the function, not any data, to the event handler, but didn't realize they were creating a closure and binding data as well.

Unless a page author is using DOM Level 0 event handling (e.g., onclick attributes in the HTML markup), usually there's a setup function called on page load that hooks up event handlers to the buttons and such using some analog of the Event.observe function I've been using in this post. Sometimes those setup functions are dealing with large data sets, perhaps a big JSON or XML document retrieved via an XMLHttpRequest query, referencing that data with local variables. Then the event handlers are defined within the setup function, which means they're closures, which means...right, they keep a reference to the setup function's context, and so the large data set is retained in memory.

Now, if that's on purpose -- the page is referring back to it periodically, etc. -- that's fine. But if the data set was just to be used for setup, it's a waste of memory. I call this the "Inadvertent Closure" anti-pattern.

Here's an example:
function mySetup()
{
var setupData;
var n;

// Set 'setupData' to some large amount of data used only for setup;
// the below is just a contrived array.
setupData = [];
for (n = 0; n < 1000; ++n)
{
setupData[n] = "Item " + n;
}

// (Presumably use the setup data for something here)

// Hook up some event handlers
Event.observe(
'someButton',
'click',
function()
{
// Do something interesting
}
);
Event.observe(
'someOtherButton',
'click',
function()
{
// Do something else interesting
}
);
// (Etc.)
}
Here, a bunch of setup data is allocated and referenced via the setupData array, and then we hook up a couple of event handlers that don't need a reference to the setupData array.

Well, they may not need it, but they have it, which means that all of that data is sitting around eating up memory unnecessarily.

The good news is that it's easy to fix. There are at least two ways to fix it; the way I don't like, and the way I like. ;-)

The way I don't like: Just "null out" the big data set when you're done with it; in our example, we'd just add this line to the end of the mySetup function:
setupData = undefined;
Personally, though, I prefer modularity: Break out the bit that needs to deal with the big data set into its own function, and the setup of the event handlers in their own function:
function myBetterSetup()
{
doTheBigDataThing();
setupEventHandlers();
}
function doTheBigDataThing()
{
var setupData;
var n;

// Set 'setupData' to some large amount of data used only for setup;
// the below is just a contrived array.
setupData = [];
for (n = 0; n < 1000; ++n)
{
setupData[n] = "Item " + n;
}

// (Presumably use the setup data for something here)
}
function setupEventHandlers()
{
Event.observe(
'someButton',
'click',
function()
{
// Do something interesting
}
);
Event.observe(
'someOtherButton',
'click',
function()
{
// Do something else interesting
}
);
// (Etc.)
}
This give us a clear separation of what we're doing, and as a nice side-effect, prevents the closures from keeping our data set around unnecessarily.

At this point, a couple of you might be thinking "OMG! But that means any time I'm dealing with a big temporary data set, I need to be sure no closures are defined within that context! What if I want to act on the data set with an iteration function like in Example #5?!" Don't worry. Remember that the context is kept around because it has a reference from the closure; when the closure is released and cleaned up by the garbage collector, the context is also released and can be cleaned up by the GC. This only matters if you're keeping an enduring reference to the closure, as in the case of event handlers.

#7 and on: Your Examples!

I've tried to give some overview of closures based on examples of usage, and I hope it's been useful, but I've really only scratched the surface here; what are your examples? Post away!

Monday, 3 March 2008

Poor misunderstood 'var'

It seems most programmers coming to JavaScript from C, C++, Java, and the like equate the var statement with variable declaration statements in the languages they come from and use it the same way. And at some casual level that's reasonable; but it can lead you down a misleading path...

Consider this code:

function foo()
{
var ar;

// ...do some stuff, create an array in 'ar'...

for (var index = 0; index < ar.length; ++index)
{
doSomethingWith(ar[index]);
}
}
This is a common idiom, but a misleading one. You might think that index is only defined within the for loop (that's certainly the impression we're giving in the code). But it's not true: In fact, index is defined throughout the function -- within the loop, outside the loop, above the loop, and below the loop. The var statement defines a variable within the current scope (all of it, not just "from here on"), and unlike some other languages, in JavaScript blocks don't have any effect on scope; only functions introduce a new scope.

Consequently, the above function can be written as it is above, but also with the index declaration...

...at the top:
function foo()
{
var ar;
var index;

// ...do some stuff, create an array in 'ar'...

for (index = 0; index < ar.length; ++index)
{
doSomethingWith(ar[index]);
}
}
...at the bottom:
function foo()
{
var ar;

// ...do some stuff, create an array in 'ar'...

for (index = 0; index < ar.length; ++index)
{
doSomethingWith(ar[index]);
}

var index;
}
...anywhere in the middle:
function foo()
{
var ar;

// ...do some stuff, create an array in 'ar'...

for (index = 0; index < ar.length; ++index)
{
var index;
doSomethingWith(ar[index]);
}
}
...or even all of them!
function foo()
{
var ar;
var index;

// ...do some stuff, create an array in 'ar'...

for (var index = 0; index < ar.length; ++index)
{
doSomethingWith(ar[index]);
}

var index;
}
We can get away with that last one because a var statement defining a variable that already exists in the current scope does not replace the variable (this is what keeps you from accidentally masking your function's arguments, or even the arguments array that's provided for you).

This seems like an odd way to define the var statement until you get into the plumbing of JavaScript and how it sets up calls to functions. You can get into some of that by reading my earlier post, Closures are not complicated, but the net effect of the plumbing is that all var statements are treated as though they were at the top of the function (if they have initializers, those become assignments and stay where they are).

So does that mean that the common idiom of declaring an indexer within the loop statement is "wrong"? Well, that's a matter of perspective, and the older I get the more experience I accumulate, the less I think in terms of absolutes like right and wrong. The language spec allows it, so in that sense it's not "wrong". In some ways, it's sort of a shorthand way of telling the next person reading the code that you're going to use it for the loop (and only for the loop, right?), so in that sense perhaps it's not "wrong".

But the further your code gets from expressing what's really happening, the easier it is for someone reading the code later (perhaps you!) to get the wrong end of the stick and introduce a problem. For example, suppose you have a 30-some-odd-line function and the loop appears in within the body of a conditional about two-thirds of the way down:
function foo(someArray)
{
var thingy;
var otherThingy;

// ...20 lines of code...

if (thingy > otherThingy)
{
for (var index = 0; index < someArray.length; ++index)
{
doSomethingWith(someArray[index]);
}
}

// ...10 more lines of code...
}
Six months after you write this, Mike edits the function and needs to remember the index of something at the top so he can do something with it at the bottom; he declares an "index" variable, sets index at the top, and then uses it at the bottom, having missed the loop:
function foo(someArray)
{
var thingy;
var otherThingy;
var index;

index = findSomething(someArray);

// ...20 lines of code...

if (thingy > otherThingy)
{
for (var index = 0; index < someArray.length; ++index)
{
doSomethingWith(someArray[index]);
}
}

// ...10 more lines of code...

restoreSomething(someArray, index);
}
Mike's introduced a bug, an irritating, intermittent bug. Sometimes the restoreSomething call at the end fails for some reason; not always, mind, but sometimes. (Because index gets set by the loop, but only when thingy > otherThingy.)

Obviously, this bug could have been avoided if Mike had read through the entire function carefully before making his mods. Or if you'd chosen a different name for your index variable (in hopes of reducing the odds of Mike using it). Or it could have been caught by thorough unit tests that explore all conditions (and then Mike would have to go back and fix it).

But let's throw Mike a bone, eh? If we declare the variable in the text in the same place it's defined by the interpreter at runtime, we help him avoid making the mistake in the first place. And we like Mike, we don't want to trip him up...right?

Regardless of your decision about how to write your code, though, understanding what var is really doing can help you get that code doing what you want it to do.