JavaScript bewilders me

I saw that Simon Willison linked to an interesting JavaScript pattern yesterday, and even after trying to grok it a few times, have absolutely no idea why the code works:


var foo = function() {
    var t = new Date();
    foo = function() {
        return t;
    };
    return foo();
};

I obviously don't understand how JavaScript scopes variables and functions. I mean look at that... it's completely tripped out. It's supposed to be sort of a singleton function - if you can call it that - calculating a value the first time a function is called, and then returning that value again without recalculating it on subsequent calls.

Some logical gaps I have: redefining a function within a function affects the global scope? I guess this makes sense as the variable isn't preced by "var", and thus isn't working on a local copy. Okay. But where the hell does the t variable live? We define foo, we define t within foo, then we *redefine* foo but this time with no t variable... So in my mind this shouldn't work as either 1) the second foo function definition is working in a global scope, and thus can't get access to t, as it's been defined locally, or 2) the new function's scope is contained within the old function's scope, and thus t works like a global variable to the new function, and thus can be returned, but only the first time. After that, it seems that foo() shouldn't work, as t has disappeared along with the definition of the first foo() function.

But obviously, I have no clue. I'm going to need to pull up SpiderMonkey or Rhino and try it out in a shell, as I don't have any idea how this is supposed to work.

Make sure you read Simon's overview of jQuery as it's quite educational, even for non JavaScript experts. It's the first time I've understood why everyone seems to be raving about jQuery now.

-Russ

Update: Martin IMed me this evening to try to pound into my head a lesson on closures. If I understand the concept correctly, even though the t variable does go out of scope when the original foo() function is overwritten by the new one, a reference to t is created within the new foo() before that happens, and therefore t's value isn't erased. I would have assumed that t would return a null in this case, as its "parent" function has been overwritten erasing all sub values declared within its scope, but that's not how it works I guess. I imagine this is the source of JavaScript's memory leaks? If any variable sticks around if there's any reference to it at all, regardless of where it was declared, it seems that there'd be lots of opportunities to suck up a bunch of RAM pretty easily.

< Previous         Next >