Improving JavaScript arrays by turning them into underscore.js “collections”

Whenever I write JavaScript code, I always end up using underscore.js in some way. It feels so natural to me now that I often will include the library in my project before ever actually needing it, since I know I can turn to it. If you’re unfamiliar with how underscore.js works, I highly recommend taking a look at the link above. They describe the library as:

Underscore is a utility-belt library for JavaScript that provides a lot of the functional programming support that you would expect in Prototype.js (or Ruby), but without extending any of the built-in JavaScript objects. It’s the tie to go along with jQuery’s tux, and Backbone.js’s suspenders.

Underscore provides 80-odd functions that support both the usual functional suspects: map, select, invoke — as well as more specialized helpers: function binding, javascript templating, deep equality testing, and so on. It delegates to built-in functions, if present, so modern browsers will use the native implementations of forEach, map, reduce, filter, every, some and indexOf.

An example of a very simple filter operation:

var simplearray = [5, 4, 3, 2, 1, 6, 7, 8, 9, 10];
var greaterThanFour = _.filter(simplearray, function(item) {
    return item > 4;
}); // greaterThanFour contains a brand new array containing [5, 6, 7, 8, 9, 10]

Sometimes the syntax just feels wrong to some. As indicated by this stack overflow question

To quote:

What I was hoping for:

Make underscore’s methods more object oriented:
_.invoke(myCollection, ‘method’); ==> myCollection.invoke(‘method’);

I’ll admit, minor difference, yet still it seems nice.

What problems will I run into if I use Backbone.Collection for non-Backbone.Models?

Are there any existing implementations, or a simple way to make a generic underscore collection class?

That got me thinking… I love JavaScript… this is now a challenge.

What is the simplest way to express an underscore “collection”?

What I came up with was to modify the Array prototype to include functions that tie into underscore. I didn’t want to maintain some large library, though, like how Backbone.JS did it. So, instead, I figured I can just pull the functions out of underscore and stick them on the Array prototype like so:

// This self-executing function pulls all the functions in the _ object and sticks them
// into the Array.prototype
(function () {
    var mapUnderscoreProperty = function (prp) {
        // This is a new function that uses underscore on the current array object
        Array.prototype[prp] = function () {
            // It builds an argument array to call with here
            var argumentsArray = [this];
            for (var i = 0; i < arguments.length; ++i) {
                argumentsArray.push(arguments[i]);
            }

            // Important to note: This strips the ability to rebind the context
            // of the underscore call
            return _[prp].apply(undefined, argumentsArray);
        };
    };

    // Loops over all properties in _, and adds the functions to the Array prototype
    for (var prop in _) {
        if (_.isFunction(_[prop])) {
            mapUnderscoreProperty(prop);
        }
    }
})();

Here is the same example as above, written with the new Array prototype:

var simplearray = [5, 4, 3, 2, 1, 6, 7, 8, 9, 10];
var greaterThanFour = simplearray.filter(function(item) {
    return item > 4;
}); // greaterThanFour contains a brand new array containing [5, 6, 7, 8, 9, 10]

I like the syntax better. It feels like the filter function is part of the Array object. Actually, because of JavaScript's dynamic nature, it IS.