PhpRiot
Become Zend Certified

Prepare for the ZCE exam using our quizzes (web or iPad/iPhone). More info...


When you're ready get 7.5% off your exam voucher using voucher CJQNOV23 at the Zend Store

Eight Weeks of Prototype: Week 6, Writing JavaScript Classes with Prototype

Binding Functions for Enumerables

In the third article in this series we covered enumerables, including the each() method. Because a separate function (known as an iterator) is called when you use each(), once again any classes you are using lose their context.

Consider the code in Listing 14. In the class constructor I have defined an array of different colours. I then attempt to loop over them and call the display() method for each colour. The problem is, this inside the each loop doesn't refer to the MyClass instance.

Listing 14 The problem with using each() in classes (listing-14.html)
<html>
    <head>
        <title>The problem with using each() in classes</title>
        <script type="text/javascript" src="/js/prototype.js"></script>
    </head>
    <body>
        <div id="container"></div>
 
        <script type="text/javascript">
            var MyClass = Class.create({
 
                container : null,
 
                initialize : function(container)
                {
                    this.container = $(container);
 
                    var colors = [ 'red', 'green', 'blue' ];
 
                    colors.each(function(color) {
                        this.display(color);
                    });
                },
 
                display : function(msg)
                {
                    this.container.insert(msg + '<br />');
                }
            });
 
            new MyClass('container');
        </script>
    </body>
</html>

When you use the each() method, it is possible to pass a second argument in order to specify the context. That is, you would use myEnum.each(myFunction, myObject). Or in this specific case, colors.each(function(color) { ... }, this). This is shown in Listing 15.

Note: This second argument for binding is available on other enumerable methods, not just each(). Look at the Prototype API guide at http://prototypejs.org/api/enumerable for full details.
Listing 15 Binding enumerable function handlers (listing-15.html)
<html>
    <head>
        <title>Binding enumerable function handlers</title>
        <script type="text/javascript" src="/js/prototype.js"></script>
    </head>
    <body>
        <div id="container"></div>
 
        <script type="text/javascript">
            var MyClass = Class.create({
 
                container : null,
 
                initialize : function(container)
                {
                    this.container = $(container);
 
                    var colors = [ 'red', 'green', 'blue' ];
 
                    colors.each(function(color) {
                        this.display(color);
                    }, this);
                },
 
                display : function(msg)
                {
                    this.container.insert(msg + '<br />');
                }
            });
 
            new MyClass('container');
        </script>
    </body>
</html>
Note: Technically, you can use the bind() method if you prefer, rather than using this second argument. That is, colors.each(function() { ... }.bind(this)).

In This Article