AJAX Array Anomalies

One of the oddities with using the Prototype JavaScript library, an implementation of AJAX, is that it overloads existing JavaScript objects with additional methods enhancing functionality. The downside to this is that it causes legacy JavaScript code in certain situations cease workingy. A good example is iterating over JavaScript Arrays. There’s been a few occasions where e-mails are sent out asking why they’re getting these strange method declarations appearing in their arrays.

JavaScript Arrays can be used as associative arrays, referred to as hashes, where a name, or key, is mapped to a value. For simplicity’s sake, the monetary_hash in the example below maps coin amounts to descriptive names. One can quickly look up the description of a monetary amount, by indexing into monetary_hash. The for (var key in associative_array) construct in JavaScript allows one to iterate all name/value pairs in an associative array.

All name/value pairs are displayed in a dialog and the end of this code snippet.


<script language="JavaScript">
    var monetary_hash = new Array();

    monetary_hash['.01'] = 'penny';
    monetary_hash['.05'] = 'nickle';
    monetary_hash['.10'] = 'dime';
    monetary_hash['.25'] = 'quarter';

    s = '';
    for (var denomination in monetary_hash) {
        // Store the name and values pairs in a string
        s += denomination + " is a " + monetary_hash[denomination] + ".\n";
    }
    // Alert the name and value pairs to the user
    alert(s);
</script>

Introducing prototype.js into the above code snippet causes unexpected behavior. Additonal method declarations that Prototype injects into the Array are considered to be valid name/value pairs. One way to filter out the unwanted method declarations is to check to see if the value is not of a type function.


<script language="JavaScript" src="common/shared_v2.0/js/scriptaculous-1.8.0/prototype.js"></script>
<script language="JavaScript">
    var monetary_hash = new Array();

    monetary_hash['.01'] = 'penny';
    monetary_hash['.05'] = 'nickle';
    monetary_hash['.10'] = 'dime';
    monetary_hash['.25'] = 'quarter';

    s = '';
    for (var denomination in monetary_hash) {
        // Work-around: Only display values that are not of type function
        if ( typeof(monetary_hash[denomination]) != "function" ) {
            s += denomination + " is a " + monetary_hash[denomination] + ".\n";
        }
    }
    alert(s);
</script>

A better way to correct this problem, keeping the spirit of legacy JavaScript programming alive, is to instantiate the associative array as an Object. There are a good number of web pages that recommend using an Object as an associative array instead of using an Array.


<script language="JavaScript" src="common/shared_v2.0/js/scriptaculous-1.8.0/prototype.js"></script>
<script language="JavaScript">
    // Instantiate the associative array as an Object
    var monetary_hash = new Object();

    monetary_hash['.01'] = 'penny';
    monetary_hash['.05'] = 'nickle';
    monetary_hash['.10'] = 'dime';
    monetary_hash['.25'] = 'quarter';

    s = '';
    for (var denomination in monetary_hash) {
        s += denomination + " is a " + monetary_hash[denomination] + ".\n";
    }

    alert(s);
</script>

Switching to use soley Prototype objects, the monetary_hash is declared with a shorthand notation of $H(), declaring the object as a Hash. Alternatively, you can use new Hash().

The name/value pairs are iterated using the each method which looks drastically different from using the old JavaScript for construct.


<script language="JavaScript" src="common/shared_v2.0/js/scriptaculous-1.8.0/prototype.js"></script>
<script language="JavaScript">
    // Create a Hash object
    var monetary_hash = $H({'.01': 'penny',
                            '.05': 'nickle',
                            '.10': 'dime',
                            '.25': 'quarter'});

    s = '';
    // Use the each method to iterate over the name (key) and value pairs
    monetary_hash.each(function(pair) {
        s += pair.key + " is a " + pair.value + "\n";
    });
    alert(s);
</script>

0 comments ↓

There are no comments yet...Kick things off by filling out the form below.

Leave a Comment