I remember when I first tried using Backbone a few years ago. Because it was my first foray in "real" client-side Javascript development, it was a confusing time filled with tools and libraries I didn't understand. One of the most confusing things about it was the requirement of Underscore.js alongside jQuery. "Why do I need yet another library dependency?", I said. "What could this possibly do that we can't do in jQuery?" Man, was I naïve…

Underscore.js (and it's newer, younger, sexier cousin, Lo-Dash) are general utility libraries for Javascript. It's essentially a functional programming library for Javascript with a bunch of nice utilities thrown in for free. Originally, it started as a way to offload a lot of generic functionality out of the Backbone library (separation of concerns!), but then started to gain it's own personality as time went on.

Underscore and/or Lo-Dash are single handedly the most important Javascript utilities in my toolbelt. I use one of them for every project, whether it's client-side or server-side.

Here are just a few tips I've picked up over the years to get some extra value out of these libraries.

Boolean optional parameters

Ahh, Javascript! One of the most annoying things to wrap your head around is the "truthy" nature of the language. In Ruby, the rules of false are set and never change… something is false if it's null or false. That's it. It's super easy to remember and therefore easy to work around.

But Javascript is a totally different beast. Things are never really false, they're "falsy". According to this Sitepoint article, the following things are always falsy:

false

0 (zero)

"" (empty string)

null

undefined

NaN (a special Number value meaning Not-a-Number!)

Because of this, is makes it really tricky to check for boolean false arguments. You can't just do this:

function doAThing(boolArg) { if (!boolArg) { // This would fire if boolArg was never sent or was sent with "false" } }

Because undefined and false are both falsy in Javascript's eyes, it turns into a mess. What if we want to assume that an argument is true if it's not sent, but correctly check for false?

Underscore comes with a ton of utility functions for quickly checking if a value is a particular type. In our particular case, the isUndefined method comes in super handy and helps us make for some easy and expressive code to do what we want.

function doAThing(boolArg) { if (!_.isUndefined(boolArg) && !boolArg) { // This would fire only if boolArg was sent something, and that something was falsy } }

.tap > temporary vars

Temporary variables are ugly… there I said it. They make for code that isn't very friendly to read and are completely unexpressive. Coming from the Ruby world, I tend to try to write tiny methods that are as clean and expressive as possible. It's a great habit to be in, and one of the best things I've pulled from my time with Ruby.

So, let's say we have a method where we get a value from some other method, we make a slight modification to it, run it through a 3rd method and then return it.

In most cases, it would probably look something like this.

function somethingImporatant() { var tmp = this.getObject(); tmp.val = "Value"; doSomething(val); return tmp; }

However, you can make this a lot cleaner by not using temporary variables and instead using underscore's .tap method.

Tap is a method who's purpose was originally created so that you could "tap" into objects in the middle of a long method chain and make modifications to them. But, I've found it's great for losing those ugly temporary variables and making code more expressive.

function somethingImporatant() { return _.tap(this.getObject(), function(obj) { obj.val = "Value"; doSomething(obj); }); }

Of course, this is even better if you're using the chaining methods (which we'll discuss a few paragraphs down), but it's great even in this simple case.

Painless defaults

If you come from the Ruby and Rails world, you probably have gotten into the habit of passing methods a hash/object of options as a parameter to your methods. This allows you to basically have a limitless number of arguments in your methods without having to constantly update your method signatures.

However, this can become quickly messy. The naïve approach is to just check to see if the parameter exists, but of course, since the whole params object could be undefined as well, you further have to check for that. It would probably look something like this.

function doAthing(obj, params) { if (params && params.something) { // Do something here } if (params && params.somethingElse && params.somethingElse === 'some_value') { // Do another thing } // Repeat every time you need to look at one params value } doAThing(123, { something: 'new', })

We can clean this code up a bit by checking the params object at the top of the method. This way we can rely on all the keys in the params object being available and set to some reasonable default value. However, it still looks kind of messy.

function doAthing(obj, params) { params || (params = {}); if (!params.something) params.something = 'thing'; if (!params.somethingElse) params.somethingElse = 'else'; if (!params.oneMore) params.oneMore = 'this'; console.log(params) // { something: 'new', somethingElse: 'else', oneMore: 'this' } } doAThing(123, { something: 'new', })

This code doesn't really show show off how painful this type of boilerplate gets since there are only 3 keys represented. But imagine the params object has 20 different options? Or what if the params are actually inherited from something else and you just are adding a few more?

This is where underscore's defaults method comes in incredibly handy. It allows us to pass an object of what we think params should be, and then it will fill in any missing keys with those default values. It's an incredibly clean solution.

And the best part, if you have multiple methods that require the same (or even mostly the same) set of params keys, you can define that defaults object somewhere in your class and just pass it in.

function doAthing(obj, params) { params || (params = {}); _.defaults(params, { something: 'thing', somethingElse: 'else', oneMore: 'this' }) console.log(params) // { something: 'new', somethingElse: 'else', oneMore: 'this' } } doAThing(123, { something: 'new', })

I use this ALL the time.

Chaining

One of the things I learned from Ruby is the idea of chaining together a bunch of functional type methods. it's a beautiful workflow that allows us to not have a bunch of ugly temporary variables hanging around to do the equivalent of one unit of work.

Underscore allows us to the do the same sort of thing with most of it's methods. Instead of passing the same temporary variable to 5 different methods, you do can do it all in one expressive shot.

For a really goofy example, let's say we needed to have a method that does the following:

Take an array of words

Append 123 to the end of each word

Capitalize the words

Reverse the order

And finally, join the words together with spaces.

If I was writing straight Javascript, it would look something like this mess of code here.

function capAndJoinWords(aryOfWords) { var result = []; if (aryOfWords.length) { for (i = aryOfWords.length - 1; i >= 0; i--) { result.push((aryOfWords[i] + '123').toUpperCase()); } } return result.join(' '); } capAndJoinWords(['array', 'this', 'in', 'are', 'words', 'test']); // "TEST123 WORDS123 ARE123 IN123 THIS123 ARRAY123"

And this code is fine. It works and it's fairly safe from errors. But it's incredibly unexpressive and hard to read. Everything is done out of order from my list of functionality above.

Let's take a look at a version that uses Underscore's chain and value methods instead.

function capAndJoinWords(aryOfWords) { return _.chain(aryOfWords) .map(function(item) { return item + '123'; }) .map(function(item) { return item.toUpperCase(); }) .reverse() .value() .join(' '); } capAndJoinWords(['array', 'this', 'in', 'are', 'words', 'test']); // "TEST123 WORDS123 ARE123 IN123 THIS123 ARRAY123"

Now that is some expressive code and is super easy to read. It does everything in the order that we laid out above and it's clear what exactly it's doing.

The chain method basically take the value that's passed to it and puts it into a wrapper object. That wrapper object then has access to most of the underscore methods as they're mixed into it. When the method is called on the wrapped object, the value it's actually wrapping is passed as the first argument automatically and then replaces the wrapped object with whatever the method returns.

It then continues down the line until you hit the value method. The value method just basically unwraps the wrapper object and returns back the wrapped value.

In this case, value is returning back our modified array of string objects. Since it's just a regular array at this point, we just call join on it to make it one string and return it.

It's an incredibly elegant way to program and reminds me of a Lisp-type language, or at the very least, Ruby. This is a good thing.

Add your own methods (and chain them!)

Because Underscore doesn't come with just enough awesome stuff on it's own, it also allows to add your own methods to it. The provided mixin method allows you to add methods directly Underscore and make them as important as the map or each methods.

At the very minimum, it allows you to not pollute the global namespace with a bunch of utility methods. Underscore is going to be available to all your code anyway, so you might as well make it as a common place to include your utility methods that you use throughout.

Let's say we want to write our goofy method above for handling strings as a Underscore mixin, because we use it in a ton of different places in our app. It would look something like this.

_.mixin({ dumbify: function(items) { return _.chain(items) .map(function(item) { return item + '123'; }) .map(function(item) { return item.toUpperCase(); }) .reverse() .value(); } }); function capAndJoinWordsDirectly(aryOfWords) { return _.dumbify(aryOfWords).join(' '); } capAndJoinWordsDirectly(['array', 'this', 'in', 'are', 'words', 'test']); // "TEST123 WORDS123 ARE123 IN123 THIS123 ARRAY123"

And that's all well and good. But, in reality, it's not all that terribly useful.

The beauty of mixin, however, is the ability to add custom methods that are chainable. For the most part, you get this functionality for free. If your method is in a chain, it will receive the wrapped value as the first argument. And just as any other chained method, it will take what's returned from it and replace the wrapped value with the new value.

Below is the same code using a chain. However, I made one slight adjust to show how it works seamlessly with Underscore's native chained methods. In this case, I'm going to return just the first word of the array using Underscore's first method.

_.mixin({ dumbify: function(items) { return _.chain(items) .map(function(item) { return item + '123'; }) .map(function(item) { return item.toUpperCase(); }) .reverse() .value(); } }); function capAndGetLastWord(aryOfWords) { return _.chain(aryOfWords) .dumbify() .first() .value(); } capAndGetLastWord(['array', 'this', 'in', 'are', 'words', 'test']); // "TEST123"

Once you get the hang of this, you start finding all kinds of incredible uses. Processing arrays of data even with advanced custom functionality becomes almost mindless. It will also become a common workflow that you will learn to depend on and exploit as much as possible.

Conclusion

In short, Underscore and Lo-Dash are really amazing libraries. So amazing that one of them makes their way into just about every piece of Javascript code I write. I suggest you do the same, because there's a ton of goodness in there.

Ted Kulp Ted Kulp is a professional developer, author and technologist with over 15 years of experience from the suburbs of Philadelphia. In 2004, he created the popular content management system, CMS Made Simple and continued to run the project for over 8 years. These days, he makes his living from writing Javascript full-time, writing books, and hacking on open source. More Posts - Twitter - Facebook - LinkedIn - GitHub

Leave this field empty if you're human:

: mc4wp_form issince version Mailchimp for WordPress v3.0! Use mc4wp_show_form instead. inon line