JavaScript
Article

Getting Started with Underscore.js

By Martín Martínez

This article was peer reviewed by Agbonghama Collins and Ryan Chenkie. Thanks to all of SitePoint’s peer reviewers for making SitePoint content the best it can be!

Underscore.js is a JavaScript library, written by Jeremy Ashkenas, that provides functional utilities for a variety of use cases that we, as developers, may come across when facing a web project.

It makes for code which is easier to read:

_.isEmpty({});
// true

It makes for code which is easier to write:

_.flatten([[0, 1], [2, 3], [4, 5]]);
// [0, 1, 2, 3, 4, 5]

It offers features for which there isn’t a 1:1 native method:

_.range(5);
// [0, 1, 2, 3, 4]

It can even be used as a template engine in its own right:

_.template('<p><%= text %></p>', {text: 'SitePoint Rocks!'});
// <p>SitePoint Rocks!</p>

Underscore is a lightweight library (just 5.7kb, minified and Gzipped) and is used by a variety of big name projects, such as:

Now let’s get more specific and start diving into its main capabilities.

The Good Parts

In this tutorial, I’m going to highlight three of Underscore’s most common methods:

I’ll explain how they are used individually, then tie them together to build a demo application that you can find at the end of the tutorial. As ever, the code for this demo is available on Github.

If you wish to follow along with the examples, you’ll need to grab a copy of the library, for example from your favourite CDN:

<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"></script>

And if you find yourself in need of help along the way, or you’re just curious to find out more, don’t forget that Underscore’s documentation is extensive. It also has a large and active community, meaning help is easy to find.

_.each: Write Readable Loops

There is not a single project that does not have something similar to this snippet at some point in the code:

var artists = ['Pharrel Williams', 'Led Zeppelin', 'Rolling Stones'];

for(var i = 0; i < artists.length; i++) {
  console.log('artist: ' + artists[i]);
}

Underscore enables you to write equivalent code, using a syntax that is more readable:

var artists = ['Pharrel Williams', 'Led Zeppelin', 'Rolling Stones'];

_.each(artists, function(artist, index, artists) {
  console.log('artist: ' + artist);
});

Neat, eh? _.each() takes two parameters:

  • The array (or object) to iterate over.
  • A callback function.

For each element in our array _.each() will invoke the callback function (referred to in the documentation as iteratee). Inside the callback we get access to a further three parameters:

  • The value of the array for the current iteration index (artist). For example, for the snippet above we’d get “Pharrel Williams” for the first iteration.
  • The number of the current iteration (index), which in our case will vary from 0 to 2.
  • The array that we are iterating through (artists).

As you can see the code is more readable and we can access the individual elements in the array without the need for artists[i], as we saw in the example that used a for loop.

See the Pen _.each by SitePoint (@SitePoint) on CodePen.

Next, we’ll see how the templating engine behaves.

_.template(): Intuitive and Straightforward

Since the rise of the Single Page Application, having a reliable frontend templating engine has become a fundamental need for our working stack.

Underscore provides a templating engine, which, for those familiar with languages such as PHP, or Ruby on Rails, will seem quite familiar.

Carrying on from our previous snippet, we’ll demonstrate how _.template() works. We’ll do this by adding a couple of lines to our code as shown below:

var artists = ['Led Zeppelin', 'ACDC', 'Rolling Stones'],
    artistTemplate = _.template('<li><%= artist %></li>'),
    content = '';

_.each(artists, function(artist, index, artists) {
  content += artistTemplate({
    artist: artist
  });
});

var container = document.createElement('ol');
container.innerHTML = content;
document.body.appendChild(container);

Here we are invoking the _.template() function with a string argument, which includes some data inside delimiters (<%= artist %>). When invoked in this way, _.template() returns a function which we can use again and again.

We can invoke our new function using artistTemplate(), passing it an object literal as an argument. This will return the string we originally passed to _.template(), substituting any object properties which correspond to the template’s free variables. In our case <%= artist %> will be substituted by the value in the artist attribute of the object.

Underscore’s templating engine, does not only allow for single values to be replaced, but also the execution of scripts inside the template itself. With a single modification, we can make our snippet even more powerful.

var artists = ['Led Zeppelin', 'ACDC', 'Rolling Stones'],
    artistTemplate = _.template(
      '<% _.each(artists, function(artist, index, artists) { %>' +
        '<li><%= artist %></li>' +
      '<% }); %>'
    ),
    content = artistTemplate({
      artists: artists
    });

var container = document.createElement('ol');
container.innerHTML = content;
document.body.appendChild(container);

We have incorporated our call to _.each() into the string that represents our template, which leads us to change the way the template is invoked. Since we are now iterating inside the _.template() function, we can pass the complete artists array to artistTemplate() (previously we were passing the individual artists). The output of this code will be the same as in the previous example.

When we want _.template() to evaluate JavaScript code, we just have to surround our code between <% %> instead of <%= %>.

Since invoking a template generated by _.template works just as invoking a function, we can take our snippet one step further and have one template called from inside another, by using the <% %> tags. This way, we can make reusable templates, since we can have a different wrapper template for our artists list and just invoke the template for each of the items it contains.

See the Pen _.template() by SitePoint (@SitePoint) on CodePen.

Finally, let’s take a look at the _.filter() function.

_.filter(): All You Need Is a Boolean Function

_.filter() receives an array and a callback function as arguments. It then invokes the function for each of the elements in the array and returns a new array containing those elements for which the function evaluated to something truthy.

Our callback function will also receive three arguments, as in the _.each() case: the element in the array corresponding to the current iteration index, the index of the iteration and the array itself.

To clarify this, let’s make a couple of modifications to our snippet.

var artists = ['Led Zeppelin', 'ACDC', 'Rolling Stones'],
    artistTemplate = _.template(
      '<% _.each(artists, function(artist, index, artists) { %>' +
        '<li><%= artist %></li>' +
      '<% }); %>'
    ),
    content = artistTemplate({
      artists: _.filter(artists, function(artist, index, artists) {
        return artist === 'ACDC';
      })
    });

var container = document.createElement('ol');
container.innerHTML = content;
document.body.appendChild(container);

As you may have guessed, in our template we’ll receive ['ACDC']as the array argument. Here’s a demo of what we’ve got so far.

See the Pen _.filter() by SitePoint (@SitePoint) on CodePen.

Enough said. Let’s get things working for something that makes a little more sense.

Our Demo Application

Don’t forget, the code for this demo is available on Github.

We’ll build a small application which consumes an API, displays the information obtained and allows the user to filter what is being shown. For this purpose we’ll be using:

More specifically, the application will fetch some artist information from Spotify and by using Underscore _.template, _.each and _.filter, we’ll display it on the page and allow the user to narrow the results by genre.

To do this, we’ll divide our code into three different modules:

  • _isAwesome.Config: holds the information that we’ll use across the application.
  • _isAwesome.Template: takes care of the template compilation.
  • _isAwesome: this is the main module which is responsible for responding to user actions and updating the UI.

All of them follow the Module Pattern.

Config Module

The Config module contains the ids of the templates to be used, together with the URL of the API that we’ll query, plus the ids of the artists that we want to get from Spotify. This way, we can add more artists by just adding further elements to the array.

Template Module

This module is the one in charge of compiling the templates, by calling getTemplates() in the Config module.

Main Module

This module is responsible for sending the Ajax request to the URL we get from the Config module and rendering the content using the templates from the Template module.

Aside from that, this module also takes care of filtering the items based on the filter clicked by the user.

Both the filters and our templates are included as part of the HTML.

To implement the filtering, we will rely on HTML 5 data attributes and jQuery’s data interface. This is more a question of convenience, but should you wish to do this natively, browser support is very good.

This is the markup of the buttons we’ll use to do the filtering:

<button class="btn btn-default sized"
        data-filter-field="genres"
        data-filter-value="album rock"
        data-action="filter">Album Rock</button>

This is an example of an object we’ll be passing to our filter function:

{
  action: 'filter',
  field: 'genres',
  value: 'rock'
}

We’ll have the HTML for our templates as part of our index.html, inside a <script> tag, which we prevent from being executed by setting its type to something different than the usual text/javascript. Just for the sake of consistency we’ll set it to underscore/template.

We’ll have two templates. The first will contain the list of artists, whereas the second will contain the individual artists to be displayed. As we saw above, we’ll use what we call embedded templates. We’ll be invoking one template ('item-tpl') from within another one ('item-list').

Then, at the bottom of the file we’ll include our libraries and our three scripts. Also, just to make it more visually appealing, we’ll have some basic styles in the header.

And that’s it.

See the Pen Underscore Awesomeness by SitePoint (@SitePoint) on CodePen.

Conclusion

Underscore is a joy to work with and, as I have demonstrated, it allows you to write clean, readable and easy-to-maintain code.

There are a couple more things that we could have added to our application (e.g. having our filters dynamically generated by using _.pluck()), but I think we have enough as to get started.

How about you? Have you worked with Underscore? Would you be willing to give a try? Did you try an alternative (i.e. lodash) that provides similar capabilities? Let me know in the comments below.

Free Guide:

7 Habits of Successful CTOs

"What makes a great CTO?" Engineering skills? Business savvy? An innate tendency to channel a mythical creature (ahem, unicorn)? All of the above? Discover the top traits of the most successful CTOs in this free guide.

  • markbrown4

    Underscore is great, where there are 1:1 native methods I prefer using JavaScript proper though, each and filter fall into that category for me. debounce, without and groupBy are my personal favourites

    • http://causeicanwrite.com Martín Martínez

      Hi Mark,

      Thanks for reading and also for your comment.

      I do agree with you: I’d also rather take into account native methods, over having a library for doing the same thing. But one important detail that I may have ommitted in the article is that Underscore degrades gracefully, running the native functions when available.

      So, when you call _.each() or _.filter(), running your application on a browser that natively supports these functions, then those ones will be executed, instead of the Underscore’s own implementation.

      About your three favorites, I must say that _.groupBy() has helped me several times, since implementing that same functionlity “by hand” is always boring and here you just have to do a callback, returning the attribute that you’d like the grouping to be done by.

      Cheers!

      • Mariusz Kujawski

        Looking at the source code _.each doesn’t do native forEach() call which is supported in IE9+ and all other major browsers. There is no point in using Underscore’s _.each method. Unnecessary overhead. Same goes for _.filter() and _.map().

        • http://causeicanwrite.com Martín Martínez

          Hi Mariusz,

          Thanks for your comment.

          You are right about how it degrades. My mistake. I will update my other response.

          Although Underscore.js does run the native functions when avaliabie, it only goes up to ECMAScript 5. Hence, Array.prototype.filter(), Array.prototype.each() and Array.prototype.map() would not actually be called, since all of them are part of ECMAScript 6.

          Thanks for bringing that into attention.

          On what comes to either using Underscore.js or not, I do agree that it does not allow for stuff which you wouldn’t be able to do without it. But it does allow for better code readibility, and more importantly as sad as it is, I don’t think we are at a point where we can deprecate everything that’s under IE9.

          Meanwhile I do agree with you on the fact that it’s ridiculous (since Microsoft itself has already dropped support for versions from 8 and ahead), I think there are still users out there who may not be that up to date and should still be able to use whatever we build.

          Once again, thanks for reading and good catch on the source code.

          Cheers!

    • http://causeicanwrite.com Martín Martínez

      Hi Mark,

      Thanks for reading and also for your comment.

      I do agree with you: I’d also rather take into account native methods, over having a library for doing the same thing. But one important detail that I may have ommitted in the article is that Underscore degrades gracefully, running the native functions when available.

      So, when you call _.each() or _.filter(), running your application on a browser that natively supports these functions, then those ones will be executed, instead of the Underscore’s own implementation.

      About your three favorites, I must say that _.groupBy() has helped me several times, since implementing that same functionlity “by hand” is always boring and here you just have to do a callback, returning the attribute that you’d like the grouping to be done by.

      Cheers!

  • M S i N Lund

    Good parts, check…

    So what are the bad parts?

    • http://causeicanwrite.com Martín Martínez

      Hi M S I N Lund,

      Thanks for reading and for your comment.

      I sincerely don’t think there are bad parts. It was just a small word play with Crockford’s book title.

      Cheers!

    • http://causeicanwrite.com Martín Martínez

      Hi M S I N Lund,

      Thanks for reading and for your comment.

      I sincerely don’t think there are bad parts. It was just a small word play with Crockford’s book title.

      Cheers!

  • Jano

    Very well written JS as module pattern

    • http://causeicanwrite.com Martín Martínez

      Hi Jano,

      Thanks for reading and I’m glad you liked the code.

      Cheers!

    • http://causeicanwrite.com Martín Martínez

      Hi Jano,

      Thanks for reading and I’m glad you liked the code.

      Cheers!

  • http://causeicanwrite.com Martín Martínez

    Hey Guilherme,

    Thanks for reading and for your comment.

    I’ve just seen the video you provided and even though I think those are valid points for showing that Underscore is not *as functional* as it claims to be, I find it hard to consider any of the demos shown ever close to motives to not be using the library.

    The way I see them, I wouldn’t actually say these are “problems” (or “bad parts”) that Underscore has, since all of the points proposed tend to highlight the difference between how the library is marketed and the things it’s lacking of to be “more” functional.

    But as I said, thanks for bringing this up and I do agree that if we think of the library from a purely “functional” perspective, the options presented in the video are really good points for Underscore.js team to keep in mind.

    Cheers!

  • http://villageprogrammer.com/ Sivaprabu Ganesan

    Hi @Martin Martinez ,

    Thanks for sharing good article..

    Last update (1.8.3 / April 2, 2015; 8 months ago) have any future updates or support ?

    • http://causeicanwrite.com Martín Martínez

      Hi Sivaprabu,

      Thank you very much for reading.

      I hadn’t dig into that, but now that I’ve checked I have not found any information regarding future releases.

      On what comes to support, since the project is hosted in Github you are always invited to raise any issue that you may find. Otherwise, on what comes to finding help for whatever you’d like to achieve with the library, for sure you’ll find a suitable solution in the web.

      Glad to hear you enjoyed the article, by the way.
      Cheers!

  • http://villageprogrammer.com/ Sivaprabu Ganesan

    Hi Martín Martínez ,

    in below example

    var artists = [‘Pharrel Williams’, ‘Led Zeppelin’, ‘Rolling Stones’];

    _.each(artists, function(artist, index, artists) {

    console.log(‘artist: ‘ + artist);

    });

    why we pass the artists _.each(artists, function(artist, index, artists) ?

    • http://causeicanwrite.com Martín Martínez

      Hi Sivaprabu,

      In this case, there is not a particular reason for doing so, but just showing the available parameters you’d get in the callback.

      Let me know in case of need for further explanations.
      Cheers!

    • http://blog.gldraphael.com gldraphael

      you can also do something like:
      _.each(artists, function(obj, i, list) {
      // list will be the same as artists
      // i will be the current index
      // obj will be list[i]
      });
      Hope this makes it clearer.

  • William Campbell

    underscore is awesome.

    I recently bombed a technical interview where I was asked to write functions that would have the same output as the underscore function in question.

    Loved the exercises but while under pressure I kept making too many mistakes. Even typos.

    Thanks for the article Martin!

    • http://causeicanwrite.com Martín Martínez

      Hi William,

      Thanks for reading.

      You are right. Even though Underscore mostly cover some of the common use cases we face on almost a day to day basis, trying to have them developed yourself can get tricky.

      I hope you did well. :)
      Cheers!

  • http://causeicanwrite.com Martín Martínez

    Hi Bob,

    Thanks for your comment.

    I do agree with the three points you commented on. It’s good to see a jsperf that shows the 3rd point.

    Particularly, point 1 is what I think we should keep in mind. Since as I said in my other comment, even though it already sounds silly, we must care for users that may still be browsing on old browsers.

    Cheers!

  • http://causeicanwrite.com Martín Martínez

    Hi Jordan,

    Thanks for your comment.

    The point that you brought up is an excellent one. By invoking the function as you mentioned we would be saving ourselves from writing the entire callback function.

    But as said in the article, since it’s just a “getting started” post we’d rather keep it to understanding the very basics, before diving into more advanced uses.

    Very interesting work on the ESLint plugin, by the way.

    I hope you enjoyed the article.
    Cheers!

Recommended
Sponsors
Because We Like You
Free Ebooks!

Grab SitePoint's top 10 web dev and design ebooks, completely free!

Get the latest in JavaScript, once a week, for free.