One problem in WWWTC # 16 is the assumptions Estelle makes about this. In C# you don’t need to explicitly use the this keyword to reference an instance field from inside an instance method. It’s tempting to write a method like Estelle’s …
… only to find out the method tries to access a global variable named _input and a global variable named _initialValue. In ECMAScript we need to explicitly bring this into play to reference entries in the object’s own dictionary:
Thanks to delegate inference in C#, it’s also tempting to think we can assign an instance method to a DOM event …
… only to find out we’ve simply given the DOM event a reference to a function object. The DOM element will happily invoke the function directly and without using an instance of an InputManager object. Our this reference inside of the resetToInitalValue function is then useless. Similar code in C# will work, because the C# compiler will magically create a delegate behind the scenes, and that delegate will manage an object reference, and invoke an instance method through that object reference.
There are mechanisms in ASP.NET AJAX to fix the above scenario, but in the end it boils down to giving the DOM element a function object that can remember the proper this reference. A simple approach would look like:
Here we are using the magic of a JavaScript closure to create and return a new function object from inside createDelegate. The DOM event will reference this new function object. When this new function object is invoked by the DOM element, the new function sets up a proper invocation of resetToInitialValue by using Function.apply and passing through the InputManager reference to use as the this reference.
We’ll explain this topic of closures and Function.apply more thoroughly in the future.
Those fixes should get the code working for now, but what else in that code was a monster in the closet?
For one, the event handler registration could use some work. There are tons of JavaScript code and articles written on the topic of how to do safe, non-desctuctive, cross-browser event registrations, so for now I’ll just say if you are using something like ASP.NET AJAX’s $addHandler technique your code will improve over the above approach.
Secondly, it’s good practice to clean up event registrations. The code sets up a scenario where each InputManager holds a reference to DOM element (in the _input field), and that same DOM input holds a reference back to it’s InputManager (via the function object / event handler that formed a closure over the InputManager instance). In the past, these circular references created memory leaks and were a common “memory leak pattern” in Internet Explorer. I say “in the past” because these problems are fixed in IE7 (and in IE6 (with an update)). Still, the generally accepted practice in today’s AJAX patterns is to clean up afterwards, which feels like the right thing to do as not all browsers are perfect in figuring out these circular references.