Underscore.JS: Your Helpful Library

Hey reader! First of all a happy happy new year! 🎉 Wishing you happiness, prosperity, good health, and success in the year ahead! \:D/

For this blog post,  we’ll be looking into Underscore.JS. As described in the Underscore.JS page,  Underscore is

“a JavaScript library that provides a whole mess of useful functional programming helpers without extending any built-in objects.”.

In a bird’s eye view, functional programming is the use of functions to transform values to other structures or into units of abstraction (and indeed Underscore provides a battalion of functions that you can use as is or use inside other functions).

Most blog posts say that if you miss the usual functional methods (available in most functional programming languages like Ruby) in your Javascript code then, Underscore is for you!

Screen Shot 2016-01-07 at 5.06.40 PM.png

Underscore.JS Website

Looking through the available functions and sample code, indeed, it’s true! Underscore provides a wide array of functions including pluck, map, and reduce which we see (and use) most of the time with our server code and other functional programming languages. With these, it is much easier to manipulate and transform data even on the client side.

To see a quick sample:

Let’s say we have this array:

var ratings = [80, 90, 99, 98, 100, 60, 50, 70];

And we want to add 5 to each of the array elements. With pure JavaScript, we do this:

for(i = 0; i < ratings.length; i++) {
   ratings[i] = ratings[i] + 5;
}

But with Underscore on, we can do a simple one-liner:

ratings = _.map(ratings, function(rating) { return rating + 5;});

Tadaaaa! Sweet and simple isn’t it? So now let’s get it going with Underscore.js.

Including Underscore.JS in our File

To utilize Underscore, we need to first load it in our page. There are many methods to achieve this depending on your need, you can have bower, npm (Node Package Manager), Require.JS, among others. For this blog post, I downloaded underscore.js and included it in our page.

http://underscore.min.js

We can check that is indeed loaded, by typing “_” in our console:

Screen Shot 2016-01-07 at 7.05.29 PM.pngNow that we have Underscore is loaded, we can start coding either by typing in the browser console or adding JavaScript code to in our html file.

 

Getting Started with Array, Collections, and Objects

As you may have observed, all of Underscore’s functions can be invoked on “_” (but we could also change this as we’ll see later on :D)

On the left side of Underscore’s page, you can see the multitude of functions available in the different categories of Collections, Array, Functions, Objects, Utility, and Chaining.

In this blog post, we’ll see a few examples from those categories and we’ll see how we can combine them to form more complex queries.

For the examples below, this is the dataset that we will be working on:
Screen Shot 2016-01-07 at 7.22.37 PM.png

_.each

We can use _.each to iterate over an objects (that can be enumerated)

For example we want print the items and the category where they belong:

_.each(grocery, function(item) {
 console.log(item.name + " belongs to " + item.category)
 });

Screen Shot 2016-01-07 at 7.30.02 PM.png

_.pluck

Similar to Ruby’s pluck, we can use pluck when we want to extract a list of values for the given key (think of it like a shortcut to map when just getting the values).

For example, if we want to get all the names of the items in our grocery list, we could do:

_.pluck(grocery, 'name')

Screen Shot 2016-01-07 at 7.30.40 PM.png_.filter

Returns the elements in the list that returns true for the given condition.

Say we want to get all grocery items with price less than 50, we can have:

_.filter(grocery, function(item) { return item.price < 50; })

* _.filter is now the preferred name for _.select as mentioned in the official documentation but using _.select still works so far (you might see this often in other Underscore.JS blogs and tutorial). 🙂

Screen Shot 2016-01-07 at 7.33.50 PM.png

_.defaults

In case there are some undefined properties, _.defaults fills them up for you depending on the default values that you provide.

grocery = _.map(grocery, function(item) {
 return _.defaults(item, {name: 'Unnamed', category: 'Uncategorized', subcategory: 'Unsubcategorized'});
 });

Screen Shot 2016-01-07 at 7.39.30 PM.png

On our remote controlled car object (last item in the list), we can see that after we ran _.defaults, category and subcategory were filled in and were set to Uncategorized and Unsubcategorized repectively.

 

_.pick

In an object’s sea of attributes, when you only want certain attributes, you can use _.pick.

Let’s say we want our array grocery to have objects that only include name and category, we can do:

console.log(_.map(grocery, function(item) {
 return _.pick(item, 'name', 'category');
 }));

Screen Shot 2016-01-07 at 7.46.32 PM.png

_.reduce

The reduce function allow us to compress a list to a single value.

For example, we want to add all the prices of our items. In our callback, we first pass acc, our accumulator and item, the variable upon which the elements of the list will be assigned to in the loop.

_.reduce(grocery, function(acc, item) {
 return acc + item.price
 }, 0);

Screen Shot 2016-01-07 at 7.47.22 PM.png

_.groupBy

_.groupBy groups the list of a list into categories and returns an object with the categories as keys and with arrays containing the items that fit into that certain category.

_.groupBy(grocery, function(item) { return item.category })

Screen Shot 2016-01-07 at 7.50.24 PM.png

_.countBy

_.countBy on the other hand, groups a list in categories that you can specify and returns how many belonged to the specific category.

Here, we counted how many belonged to the different price ranges, 1-30, 31-60, 60-100, and 100 and above.

_.countBy(grocery, function(item) {
   if (item.price < 30) return '1 - 30';
   if (item.price < 60) return '31-60';
   if (item.price < 100) return '60-100';
   return '> 100';
 });

Screen Shot 2016-01-07 at 7.48.00 PM.png

_.range

_.range, on the other hand, is a handy function that gives the values within the given range (start inclusive, end exclusive) by increments of the given third parameter.

_.map(_.range(1, 12, 1), function(day) { return 'Day ' + day + ' of Christmas!'});

Screen Shot 2016-01-07 at 7.48.51 PM.png

Doing _.range(0, 10, 2), on the other hand, gives 0, 2, 4, 6, 8. And having a negative incrementor like _.range(99, 0, -1) gives the numbers from 99 to 1 in descending order.

 

Continuing with Function and other Utility Functions

_.once

Another handy function from Underscore is _.once, it allows the wrapped function to be ran only once. Succeeding calls to the wrapped function just returns the given previous value.

generateRaffleCoupon = function() {
 // Assigns only one unique raffle number per user. 
 var points = _.random(10);
 return points
}
a = _.once(generateUniqueId)

Screen Shot 2016-01-07 at 11.31.09 PM.png

 

In the above example, only one raffle number can be assigned to a user and succeeding calls to our simple raffle number generator just gives the already assigned number.

The original unwrapped function, generateUniqueId(), on the other hand, just behaves normally and can gives different values for different calls as we can see in the last two calls.

_.times

_.times invokes the given function for the given number of times.

_.times(5, function(i) { console.log('hi ' + i)});

Screen Shot 2016-01-07 at 7.52.04 PM.png

 

Method Chaining

Above, we saw a lot of handy functions that you should let you go up and running (but of course there are still so much more that you should also check out the official documentation :D)

As we mentioned above, functional programming involves the use of functions to accomplish a certain task, either to transform objects or to simplify and reduce an object or list to a single value. And in accomplishing a task, we may use not only one, but a series of functions to get our desired result. For this purpose, we can do method chaining.

Calling _.chain returns wrapped objects so we can only get the value until we call  .value() on our chain.

console.log(_.chain(grocery).map(function(item) {
 return item.category + ' Product';
 }).uniq().value());

Screen Shot 2016-01-07 at 7.51.01 PM.png

Underscore.JS as a Templating Engine

Say we have a dynamic page that should say “Hello <name of user here>“. We need to have our html code evaluate a dynamic value that will be passed to it. For this purpose, underscore’s _.template comes handy.

So how do we do it?

First, let us declare our template and enclose the dynamic values with the default interpolation delimiter of Underscore <%= %>.

var template = 'Hello <%= name %>! Welcome to this site!';

And then let’s compile it with _.template,

var finalTemplate = _.template(template);

which returns as with a function that we can call.

console.log(finalTemplate({name: 'John Doe'}));

Screen Shot 2016-01-08 at 10.05.41 AM.png

 

We now have our html code with the name variable replaced by the given parameter. To use this, what we can do is just assigned result ot html (for ease of use, I also used jQuery for DOM manipulation):

result = finalTemplate({name: 'John Doe'});
$('#header-txt').html(result);

 

Other Configurations

As mentioned above, there are several customizations that you can do with Underscore and here are some of them:

I. Changing _

We can change _ to other characters or set of characters that you like (maybe you want to do this if you have other use for the underscore character like storage for the last value), you can do the following:

var uscore = _.noConflict();

So now, we can use uscore instead of _

events = ['New Year', 'Graduation', 'Birthday', 'Anniversary'];
console.log(uscore.each(events, function(event) { console.log('Happy ' + event  + '!!!')}));

Screen Shot 2016-01-07 at 5.01.03 PM.png

But bear in mind that when you do this, _ no longer is usable, unless you re-assign. 

Screen Shot 2016-01-07 at 5.01.49 PM.png

II. Object Orientedness

scores = {'Bob': 1, 'Alice': 4, 'Mallory': 3};
(scores).keys();
(scores).invert();
(scores).keys().map(function(p) { return "Hi " + p + "!"; })

When doing this object oriented style, of using Underscore.JS, you can immediately chain functions without using _.chain.

Screen Shot 2016-01-07 at 4.58.21 PM.png

III. Customized Template Delimiters

In case we want to change the delimeters from being <% %> to something else of our liking, we can do so by proving custom interpolation and evaluation regular expressions parameters to _.templateSettings.

In this example, we changed <%= %> to {{ }}

_.templateSettings = {
 interpolate: /\{\{(.+?)\}\}/g,
 evaluate: /\<\%(.+?)\%\>/g
 };

Screen Shot 2016-01-07 at 8.15.59 PM.png

Sample application

So now, we try to build a sample application that uses Underscore.JS for data processing as well as a templating engine.

Say we have a product inventory, where our list of grocery items is displayed plus the user can also add more items.

Screen Shot 2016-01-07 at 5.48.35 PM.png

The full source code can be found in this gist.

In implementing this, we used the following:

 

  1. Use of Defaults

    We allow empty categories and subcategories in our form so we need to fill them up with defagrocery = _.map(grocery,

    function(item) {
       return _.defaults(item, {name: 'Unnamed', category: 'Uncategorized', subcategory: 'Unsubcategorized'});
    });

    Screen Shot 2016-01-07 at 5.50.14 PM.png

  2. Use of Templates

    We also used templates to display dynamically our table. We call the updateView() function when the page loads and every time an item is added to our grocery list. Screen Shot 2016-01-07 at 5.50.37 PM.pngScreen Shot 2016-01-07 at 5.50.29 PM.png

  3. Customized Template Delimiters

    We changed the interpolation delimiters from <%= %> to {{ }} and retained the evaluation delimiters as <% %>.

    Screen Shot 2016-01-08 at 10.14.55 AM.png

  4. Some Functional Programming

    We standardized our error and warning messages by creating the fail and warn methods which we can call anywhere accordingly.

    Screen Shot 2016-01-07 at 5.57.20 PM.png

    We also created a parser for our input which is called before we push our the new item to our grocery list. This parser calls our fail and warn functions.

    Screen Shot 2016-01-07 at 5.50.56 PM.png

Demo:

output_ujipux.gif

There, as we saw, Underscore.JS is very helful and provides tons of functions that we can use to manipulate our data on the client side. With a mere 4 KB file size, it can already do wonders! Try it now! 🙂

References: