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.

How does JavaScript Scope work?

In a previous post, I reviewed how JavaScript treats the “this” keyword.. In this post, I want to talk about how JavaScript defines scope. As a C# programmer coming to JavaScript a few years ago, I did not know this fact, and thus I assumed my C# knowledge of “this” and scope would follow to JS.

Only functions create scope in JavaScript

Take the following C# code for example:

public int x = 1; // this is a class member, and thus is scoped to the class instance
void Foo()
{
    if (true)
    {
        int i = 1;
    }
    // i is inaccessible here, because it is scoped to the if block
}

And the following javascript code:

var x = 1; // Variables not declared in a function are global
function foo() {
    if (true) {
        var i = 1;
    }

    alert(i); // This is perfectly legal, and I is accessible here.

    // Any variables declared here are scoped to the function foo.
    // To force scope:
    (function () {
        var y = 1;
        z = 2; // Declare a variable in the global scope by leaving out the var keyword!
    })();
    // y is not accessible here, because it was declared inside of a function
    // an anonymous self executing function still creates scope
}

alert(z); // z is undefined
foo();
alert(z); // z is 2 after running foo().
alert(window.z); // z is attached to the window object because it was declared without var!

Pay attention to the comments, please. Especially the bit about leaving out var, creating a globally scoped variable attached to window.

This can be a big sticking point for developers coming from C# or Java where scope is very different. Many bloggers will take this type of post to the extreme and explain other concepts like closures and prototype, as well as combining the topic of context binding the “this” keyword, but I am keeping this succinct for a reason. I’ve already covered “this” in a previous post, and I can probably do a post on closures and using the prototype more in depth another time.

In my opinion, this topic stands on its own as one of the most confusing points for a developer that is new to JavaScript, so it deserves a separate post.

JavaScript and the “this” keyword

One of the things that tripped me up when I first learned JavaScript was the “this” keyword. I came from a pure OO world, where classes were clearly defined objects, and “this” always referred to the object in context. JavaScript is a prototype based scripting language, though, and as such, doesn’t have the concept of a class. The “this” keyword means something very different in JavaScript.

According to the ECMAScript language specification:

The this keyword evaluates to the value of the ThisBinding of the current execution context. 

And the “ThisBinding” keyword is:

The value associated with the this keyword within ECMAScript code associated with this execution context.

So, both definitions refer to the other, which I was always taught in elementary school was not to be done! In my opinion, this definition is rather useless to the new JavaScript developer. Practical examples are much more useful!

In JavaScript in a browser, all global functions are bound to the Window object. You can see the behavior by running this bit of code in any browser’s developer console:

(function () {
    console.log(this); // [object Window]
})();

It’s a self executing function that exists in the global scope, and the console.log(this); line should write out [object Window] or something similar. That’s because “this” is a reference to Window. In a function like this, anything that exists on the Window object is also available through the “this” keyword:

(function () {
    this.alert(0);
})();

Because the alert function exists in the global scope, it is attached to the Window object. A related phenomenon occurs when you declare global variables:

hello = function() {
    alert('hello');
}

(function () {
    this.hello(); // same as calling window.alert('hello');
})();

This is the default behavior, but that’s only when functions are declared, or rather, bound to the global scope when executed. One can easily rebind a function with .call() or .apply():

var newobj = {
    alertit: function (message) {
        alert(message);
    }
};

var func = function (message1, message2) {
    this.alertit(message1 + " " + message2);
};

func.call(newobj, 'hello', 'world'); // alerts hello world
func.apply(newobj, ['hello', 'world']); // alerts hello world

the .call() and .apply() functions are both used to change the “this” keyword binding, or the “ThisBinding” as described in the ECMAScript spec. They do the exact same thing, but they pass parameters into the called function differently. The .call() function takes a dynamic parameter set, and the .apply() function takes an array of parameters. Either way, you can see that ‘func’ is called the same way, with its “this” keyword bound to the newobj object.

In the case where a function is already scoped to an object, the “this” keyword will reference the parent object:

var NewObj = function () {};

NewObj.prototype.alert = function (message) {
    alert('NewObj alert: ' + message);
};

NewObj.prototype.test = function (message) {
    this.alert(message);
};

var newobj = new NewObj();
newobj.test('test'); // alerts NewObj alert: test
newobj.test.call(window, 'test'); // alerts test

In this case, the first newobj.test() is called while using the default binding, which is the instance of NewObj that was created, so when it calls this.alert(), it is calling the object’s prototype.alert() function.

The second time it is called, I forced a rebind to the window object, by using .call(). This causes the normal global alert() function to be the one called, since in this call, “this” is bound to window.

I hope this clears up a common problem for someone. I certainly had a hard time understanding “this” when I first learned JavaScript, but hopefully it makes more sense after seeing a few examples.