Javascript Performance Optimizations

Josh Powell

Subscribe to Josh Powell: eMailAlertsEmail Alerts
Get Josh Powell: homepageHomepage mobileMobile rssRSS facebookFacebook twitterTwitter linkedinLinkedIn


Related Topics: Web 2.0 Magazine

Web 2.0 : Article

Implementing Prototypes Array Methods in jQuery

An array jQuery plugin

One of the biggest concerns I've heard mentioned from users of the Prototype library about jQuery is the lack of support for various array methods. The robust features Prototype provides for arrays is of great benefit to developers that do a lot of array manipulation in their JavaScript.

However, I find that after moving to jQuery, I do less array manipulation than I had done with Prototype. Perhaps jQuery has altered my development pattern so I no longer need array manipulation, or perhaps I have shifted most of my data manipulation to the server. Whatever the case, I have only on occasion missed the Prototype array methods.

While there is some overlap in the ways that jQuery and Prototype handle array manipulation, jQuery does a few things Prototype doesn't do, and Prototype does a number of things that jQuery doesn't. I began writing an article about these differences, but soon got side-tracked writing a jQuery plugin to mimic the array methods Prototype provides.

You can find the plugin at http://code.google.com/p/jquery-protify-js/

With this plugin, you can give a particular array all of the methods that Prototype adds to their Array and Enumerable objects. You can use the methods two different ways. The first does not extend the original array:

JavaScript:
  1. var arr = [1,2,3,4,5,6];
  2. var protArray = $.protify(arr);

 

This will return an array extended with the Prototype library's methods, but leave the original array untouched.

The second extends the original array by passing in true as the second parameter:

JavaScript:
  1. var arr = [1,2,3,4,5,6];
  2. $.protify(arr, true);

 

In either case, the JavaScript Array prototype is untouched. When you create new arrays, it will not have the new methods. This way of writing code adds the new methods when they are needed while leaving the underlying JavaScript prototypes untouched. The return value of the methods is an array with the extended methods so that they can be chained.

JavaScript:
  1. var arr = [1,null,2,3,4,5,6];
  2. var arr2 = $.protify(arr)
  3. .compact()
  4. .findAll(function(a) {
  5. return a>=3;
  6. })
  7. .first();  // 3

 

The above code first returns the arr array values in a new array with the Prototype methods, removes any null/undefined values (using compact), finds all the values in the array greater than or equal to 3 and returns an extended array of them (using findAll), and finally returns the first value of that array (using first). It does all of this without touching the prototype for all arrays.

Here are some useful Prototype array methods included in the plugin:

all()

returns true if every member of the array == true and returns false if even one member != true.

JavaScript:
  1. var arr = [1,2,3,4,5,6];
  2. $.protify(arr, true);
  3. arr.all();  // true

 

any()

returns true if even one member of the array == true and returns false if every member != true.

JavaScript:
  1. var arr = $.protify([1,2,3,4,5,6]);
  2. arr.any(); // true

 

map()

similiar to jQuery's $.map. It executes the function passed in on every of member of the array and returns an array of the results.

JavaScript:
  1. $.protify([1,2,3,4,5,6]).map(function(n) {
  2. return n * 2;
  3. });  //  [2,4,6,8,10,12]

 

eachSlice(number)

slices the array into an array of arrays of the size passed in. There is an optional second parameter which is a function that acts on each array partition before placing it in the slice.

JavaScript:
  1. var arr = [1,2,3,4,5,6];
  2. $.protify(arr, true);
  3. arr.eachSlice(2);  // [[1,2],[3,4],[5,6]]
  4. arr.eachSlice(2, function (n) {
  5. return n.map(function(item) {
  6. return item * 2;
  7. });
  8. }); // [[2,4],[6,8],[10,12]]

 

include(value)

returns true if the value is in the array (using == equality).

JavaScript:
  1. var arr = [1,2,3,4,5,6];
  2. $.protify(arr, true);
  3. arr.include(3); // true
  4. arr.include('pie'); // false

 

max()/min()

returns the maximum/minimum value of the array. Optional parameter is a function that can be used to define the comparison and what gets returned.

JavaScript:
  1. $.protify([{'name': 'frank', 'age': 10},{'name': 'joe', 'age': 12}])
  2. .max(function(person) { return person.age });
  3. // returns 12

 

partition()

returns an array with two arrays in it. The first array contains the values that == true in the initial array, and the second all of the values != true. There is an optional parameter that is a function used to do the evaluation.

JavaScript:
  1. $.protify([1,2,3,4,5,6]).partition(function (n) {
  2. return n <= 3;
  3. });
  4. // [[1,2,3],[4,5,6]]

 

pluck()

And finally, my favorite. The pluck() method iterates through every member of the array and returns an array of the value of the attribute name passed in.

JavaScript:
  1. var arr = [{'name': 'Frank', 'age': 10}, {'name': 'Joe', 'age': 12}];
  2. $.protify(arr).pluck('age'); // [10, 12]
  3. $.protify(arr).pluck('name'); // ['Frank, 'Joe']

 

For a full listing and description of all the methods, see the Prototype documentation on arrays and enumerables.

Arrays: http://prototypejs.org/api/array

Enumerables: http://prototypejs.org/api/enumerable

The toJSON method has not yet been implemented because it depends on object methods that Prototype provides. Can you guess what my next project is?