Easy functional programming in JavaScript with Underscore.js -- part 2
In the previous post I showed how good use of Underscore.js’s map
function can substantially increase the quality of your code. This time I’ll explore some other functional collection favourites: reduce
, select
and all
.
Reduce that array over a low heat until thick and creamy
Have you ever had to do something like this?
Basically, this is going through some kind of list of values, calculating a new value from each one and accumulating some kind of answer. It’s a common pattern, and there’s an Underscore function for it! This is exactly what _.reduce
was built for:
_.reduce
takes a collection of values, a function, and a starting value. In this case, the starting value is 0 because we’re building up a running total of numbers. The function is passed the running total (which starts at 0) and each element of the collection. The return value of the function becomes the next value for the running total. _.reduce
doesn’t just need to be used on numbers:
In this case, I’m reducing an array of animal objects into a single string. Of course there are plenty of ways to do the above, but this shows you the flexibility of _.reduce
.
Bo Selecta!
Imagine you have an array of strings, but you want a new array of strings that start with a capital letter. You might do that like this:
Now, you won’t be surprised to learn that there’s an Underscore function for doing just that: introducing _.select
!
Isn’t that much cleaner? Again, we’re abstracting away the minutiae of selecting elements from a list, and just declaring that we want the elements that start with a capital letter. Simples!
All the single ladies
Sometimes you just want to know a yes or no answer about a collection. For example, are all my ladies single?
Hell yes they are. You can read _.all
as “is this statement true about all the elements in my collection?” In the same way, _.any
can be read as “is this statement true about any of the elements in my collection?”
What about this?
Here’s a useful little tip. When you’re working with nested functions in an object context, you’ll find that this
in the nested function doesn’t refer to the object’s context, but the global context. The standard way to deal with this is a line like that = this;
or self = this;
. There’s a nicer way to do this with Underscore. Nearly all the functions for working on collections take an optional context
argument, which specifies what this
will be inside the function. Here’s an example:
Because we’re passing the value of this
to _.select
, the function passed to _.select
is working with the correct this
. Otherwise, this.maxAge
would be undefined.
Learning more
I’ve only gone into some of the functionality that Underscore offers. The docs are very approachable and clear - I urge you to go and read them.
@SamirTalwar on Twitter recommended that I show the alternative syntax for Underscore, as described in the docs. Basically, instead of doing:
_.map(collection, func);
you can do:
_(collection).map(func);
And, coupled with .chain()
you can do awesome chaining things like this:
Pretty cool. Anyway, use whichever feels right to you. Enjoy!