Todd Ditchendorf advocates the benefits of anonymous classes:
While the XMLHttpRequest class is certainly a major step forward for JavaScript in the browser, you have to admit… this API is crap … Instead of passing a function reference to [the XMLHttpRequest object], why not pass a reference to a JavaScript object? … Notice how [anonymous classes] allow you to package instance properties (fields, variables, attributes, whatever) and instance methods along with the actual callback method … Sure … you don’t need this kind of functionality … you can always just define a bunch of global functions and global variables to be used by your callback function, but, then you lose all the benefits that OO offers with regard to combining state and behavior into a single, encapsulated entity!
While I agree with his statements — the XMLHttpRequest API is crap — the alternative to anonymous classes is not a mess of global variables and functions, thanks to a feature in Javascript known as closures. It seems many Javascript developers don’t know about closures, as they come from the functional, not object-oriented, line of languages, so I thought I’d highlight them here.
Javascript allows functions to return functions, and I think most Javascript developers will be familiar with that. However, some may not know that such a function can reference variables defined in it’s parent function, even after the parent has returned. This means you can write things like:
function makeSayHello(name) { var sayHello = function() { alert("Hello " + name); } return sayHello; } var noel = makeSayHello("Noel"); var matt = makeSayHello("Matt"); noel(); /* Says "Hello Noel" */ matt(); /* Says "Hello Matt" */
Notice that noel and matt refer to the arguments to makeSayHello even after makeSayHello has finished executing. This is very useful when writing callbacks, as it allows you to setup the callback with the parameters it needs avoiding a mess of globals. For example:
function makeCallback(arg1 arg2) { return function() { doSomething(arg1); doSomething(arg2); } }
You’ll see this pattern used a lot in our demos. It’s a neat trick and deserves to be better known.