Easy functional programming in JavaScript with Underscore.js -- part 1
So, you’ve been developing in JavaScript for a while, you’re getting on quite well with your for
and while
loops, when somebody comes along and tells you you shouldn’t be doing that, that JavaScript is a functional programming language and there’s much better ways to solve most problems that with loops. Whaaa…? Well, that’s what I’m here to tell you anyway.
What is functional programming?
Functional programming (FP) is all about the idea of functions as a mapping from one value to another. An FP function just turns one value into another - it doesn’t have side effects. Side effects are anything that happens within the function that changes something outside of the function. For example, changing the value of a variable not defined in the function, or logging output, or showing an alert message … basically anything that happens in the function. The only thing an FP function does is takes in a value, and returns a new value.
Another interesting thing about FP is the use of higher-order functions. These are functions that either take or return functions as values (or both). I’m mainly going to be looking at functions that take other functions as parameters, because there are some interesting things you can do with that.
Functional programming in JavaScript is made a lot easier with a suite of functions called Underscore.js all packed into a minified script of just 3kb. Underscore provides a selection of common FP functions for working on collections, like map
, each
, reduce
, select
etc. I’ll walk through some of these to demonstrate the power of FP. Note that functional programming isn’t just about working with collections - there are lots of other exciting things you can do - but for now I’ll concentrate on the collections.
Mapping over an array
One of the most widely used Underscore functions is _.map
. This takes an array and a transforming function, and creates a new array based on the return value of the transforming function. That’s a bit abstract so I’ll give you an example:
So, _.map
is passed an array, and a function. That function is called on each element of the array in turn, and the return value of the function gives the corresponding element in the new array. Note that the original array is left intact. The _.map
function takes an array, and returns another array - it’s a mapping from one value to another.
You can do much more interesting things with _.map
than just multiplying numbers though. You could transform an array of strings into an array of cats!
I hope you’ll forgive me for using two Underscore functions there. First off, we’ve got _.map
. In this case, we’re going through the array of cat names, and creating an array of cats. The second is _.each
. This, like _.map
, goes through each element of the array, passing them into the function, but it doesn’t care about the return value. It just executes the function and carries on with its life. Now, if you’re concentrating, you may have noticed that each
isn’t actually a mapping from one value to another, and you’d be right. _.each
is only useful if you allow side effects, for example console.log
ing. A JavaScript program isn’t much fun without any side effects, because you’d have no idea if anything happened otherwise. The key to functional programming is minimising the side effects.
What’s great about _.map
is that once you’ve learned to read it, and understand what it does, it really succinctly explains the meaning of your code. In that cat example, you can see that all the _.map
function is doing is turning strings into cats. That’s all you need to know. The old-school JavaScript technique would look like this:
In comparison, isn’t that just damn ugly? I mean, to read that you need to keep track of the array, and the array index, and the length of the array, and you have to make a new blank array to contain the new cats, and … you get the point. It’s mixing up the how with the what. All I care about is that I’m getting an array of cats, from an array of cat names. Don’t bother me with insignificant details like array indices.
Here’s another example: constructing a query string:
This one uses an object, but the same principles apply. From a list of key/value pairs, we’re constructing an array of ‘key=value’ strings. Then all you need to do is join
the array with &
s. This describes how a query string is formed much more declaratively than the standard
append the key, then an equals, then the value, then an ampersand, then the next key, then the next value, then another ampersand, then - oooh we’re at the end - better get rid of that last ampersand, whoops!
Go forth and map-ify!
I hope that’s given you some ideas as to how functional programming can be used in JavaScript. And I really hope that you can begin to see how much cleaner your code can get when you cast out the for
loops and embrace the _.map
. If all you’re after is map
and each
, and you’re using jQuery, you’ll be glad to know both functions have jQuery equivalents: jQuery.map and jQuery.each, albeit with a slightly different API. Next time I’ll be looking at some of Underscore’s other functions, for the times when _.map
just won’t cut it.