Exploring Drupal 8 Notes - Underscore.js

This is the first of a series of posts exploring Drupal 8.  I am going from the front-end to the back-end starting with what are probably the more obscure to less obscure components of Drupal 8 with each post.

What Underscore.js is

Underscore.js is an open source Javascript helper library intended to make common data manipulation tasks on JavaScript arrays, objects and collections easier.  At the time of writing, the size of the compressed version of the library is less than 6 kilobytes.

Why it is part of Drupal 8 core

In Drupal, Underscore.js was probably included as a Backbone.js dependency.  So, why does it get its own blog post?  Well, the library includes many useful functions that can be used not only by Backbone.js but also by jQuery and plain JavaScript.  It includes a lot of functions core to languages like PHP but not included in JavaScript.  If you do front end development, learning this function library may help improve your code quality, maintainability and reliability.

At the time of writing, the current version of Underscore.js 1.8.3 includes over 100 helper functions.  In the following paragraphs, I am going to outline a few that I think might be useful.

Iteration Helpers

Underscore has several functions that make it easy to loop over data sets.

each - The each function is useful for neatly listing (without the need to write your own for loop) all elements in an array and using the callback to return only the relevant elements like first name, last name and age for a list of people.

This function takes 2 arguments.  The first argument is the array or object that it iterates over.  The second argument is a callback function that is invoked with each object in the list.  The callback function takes 3 arguments.  The first is the current object, the second is the object’s index number in the collection and the third is a reference to the collection.

Search Helpers

Underscore also includes search functions that help you search through data sets without having to write your own loops.

find - Takes a collection as its first argument and a callback function as the second.  It finds the first element in a collection that matches the criteria in the callback function.  The callback function returns a boolean so the first element that returns true will be the returned element.

findWhere - Similar to the find function, findWhere returns the first element in the collection with all of the key-value pairs of the object in the second argument.  The first argument is a collection and the second is an object with search criteria properties.

pluck - Returns an array of all values for the property name passed in as the second argument.

contains - Searches for a value passed in as the second argument from a list of values passed in as the first argument.  Optionally, you can also pass in a starting point to iterate from as a third argument.  If the search value passed in is found, the function returns a true.

Filter Helpers

Filtering is taking a large data set and narrowing it down to a smaller data set.  Underscore has several functions to make this easier.

filter - Loops through a collection (passed in as the first argument) and returns an array of all values that pass the callback function (passed in as the second argument) test criteria.  The callback function returns a boolean.

reject - The opposite of the filter function.

where - Takes a list as its first argument and an object with a set of properties as its second argument.  The where function goes through each value in the list and returns an array of all values with the key-value pairs matching those in the properties object.

every - Loops over all elements in the list passed in as the first argument.  The second argument is a function that is called for each item in the list.  The function will only return true if the callback function returns true for every item in the list.

some - Similar to the every function but returns true if a minimum of one item in the list passes a set of criteria defined in the callback function.

Sorting & Grouping Helpers

Underscore provides several functions to make sorting and grouping neater and easier.

sortBy - Takes a list as the first argument and a function that returns a numerical value as the second argument.  It returns the list sorted by the value the function returns in the second argument.  For example, you could sort a list of people by their age.

groupBy - Similar in syntax to sortBy, this function takes a list as the first argument and a callback function as the second argument.  The callback function must return an associative array with the key being the item that was grouped on.  For a list of people, you might use this to group a list of people by their hair color.

countBy - Very similar to the groupBy function but the callback function will return an associative array with a count for the number of items that match a particular criteria.  For a list of people, you could use this to return the number of people with each eye color.

Manipulation Helpers

The Underscore library also provides several methods for easy manipulation of data within a set.

shuffle - Randomly shuffles the objects in a collection using an implementation of the Fisher-Yates shuffle algorithm.  For a card game application, this could be used for shuffling a deck of cards.

map - Takes a list as the first argument and, transforms the list using the callback function passed in as the second argument and returns a new array.  For example, in a list of people, we could write a function that returns Tall, Short, or Medium based on each person’s height.

Arrays and Objects

In addition to the functions it provides for data record sets, Underscore also has many methods to help with regular JavaScript arrays and Objects.

first - Returns the first element of the array passed in.  If an optional second numerical parameter is passed in, it will return the first x elements.

last - Returns the last element of the array passed in.  If an optional second numerical parameter is passed in, it will return the last x elements.

initial - Returns all elements of the array but the very last one.  If an optional second numerical parameter is passed, it will return all but the last x elements.

rest - Opposite of initial, returns all elements of the array but the very first one.  If an optional second numerical parameter is passed, it will return all but the first x elements.

Array Operations

without - Takes an array as the first parameter and one or more unwanted values as the second parameter(s).  It then returns an array with all instances of the unwanted value(s) in the second argument removed.

union - Takes two or more arrays and joins them together.  Union eliminates duplicates so if, for example, 2 arrays both have the number 5, the resulting array will only have one 5 and not 2.

intersection - Opposite of union, intersection takes two or more arrays and returns a new array with the common elements of both arrays.

difference - Think of the first parameter as the base array.  The second parameter can be one or more other arrays.  This function will return values in the base array that are not in the other arrays.

Object Functions

keys - Returns all property names of the passed-in object.

values - Returns all property values of the passed-in object.

pick - Takes an object as its first parameter and one or more desired properties as its second parameter.  It returns a new object with only the properties passed in as its second parameter.

omit - The inverse of pick.  It returns a new object with all of the original object properties but those passed in as keys are filtered out.

Object Operations

extend - Adds new properties to an object.  The first parameter is an object and the second is one or more properties you want to add to that object.

defaults - Assigns default values to an object.  Takes an object as the first parameter and an object with default values as the second parameter.  If no value is assigned for the object but included in the default values object, the defaults function will assign default values to one or more empty properties.  This function is often used within an iterator to assign default values to an array of objects.

clone - Makes a shallow copy of the object passed in.  If the object passed in has any array or object properties, they will not be duplicated.  They will instead be copied in by reference.  Other properties are copied in by value.

once - Makes sure the function passed in as a parameter is only executed one time.

Conclusion

The Underscore library includes dozens of other useful functions that can help you write cleaner, more elegant and more maintainable JavaScript code.  Due to its close association with Backbone, it’s often overlooked as a standalone library.  After taking a closer look at it, I think it’s underrated.  In a way, it completes JavaScript and is useful far beyond being a Backbone helper library.  From now on, whenever I need to manipulate data with JavaScript, I will check Underscore for helper libraries to do so.