Eight Weeks of Prototype: Week 6, Writing JavaScript Classes with Prototype
Function Binding
When using Prototype to develop classes, you need to have an understanding of what function binding is and how to use it. Essentially what binding does is instruct what the variable this refers to in a function. This is especially useful for event handling and for handling Ajax responses.
As I showed you in the fourth article of this series ("Event Handling in Prototype"), to observe an event on an element you use theElement.observe('eventName', handler). If you are developing a class then you want your handler function to be one of your class methods. This is primarily so you can access other class methods when handling the event.
Consider the code in Listing 10. In this example, when the user clicks the button the _onButtonClick function is called. Our aim is to display the string returned by the getMessage() method when the button is clicked.
This code will not yet work, as explained following the listing!
<html> <head> <title>Demonstrating the drawback of not using function binding</title> <script type="text/javascript" src="/js/prototype.js"></script> </head> <body> <div> <input type="button" value="Click Me!" id="myButton" /> </div> <script type="text/javascript"> var MyClass = Class.create({ initialize : function(button) { button = $(button); button.observe('click', this._onButtonClick); }, getMessage : function() { return 'This is a simple function'; }, _onButtonClick : function(e) { var button = Event.element(e); var message = this.getMessage(); button.up().update(message); } }); new MyClass('myButton'); </script> </body> </html>
The problem that occurs in this example is that when _onButtonClick runs, the getMessage() method is not found. This is because the keyword this doesn't refer to the instance of MyClass.
To solve this problem, Prototype provides two methods: bind() and bindAsEventListener(). They are basically the same thing, the difference being that you should use bindAsEventListener() specifically when you are observing events, because then Prototype knows to pass in the event object to the callback handler.
Listing 11 demonstrates usage of the bindAsEventListener(). This method accepts a single argument: the variable to bind the function to.
<html> <head> <title>Binding variable with bindAsEventListener</title> <script type="text/javascript" src="/js/prototype.js"></script> </head> <body> <div> <input type="button" value="Click Me!" id="myButton" /> </div> <script type="text/javascript"> var MyClass = Class.create({ initialize : function(button) { button = $(button); button.observe('click', this._onButtonClick.bindAsEventListener(this)); }, getMessage : function() { return 'This is a simple function'; }, _onButtonClick : function(e) { var button = Event.element(e); var message = this.getMessage(); button.up().update(message); } }); new MyClass('myButton'); </script> </body> </html>
Now, inside the _onButtonClick() method, this refers to the instance of MyClass, meaning the getMessage() method can now be called.


