Book Image

Learning Underscore.js

By : Alexandru Vasile Pop
Book Image

Learning Underscore.js

By: Alexandru Vasile Pop

Overview of this book

Table of Contents (14 chapters)
Learning Underscore.js
Credits
About the Author
About the Reviewers
www.PacktPub.com
Preface
Index

Key Underscore functions


Out of the many Underscore functions, there are a couple that deserve special attention as they provide a good introduction to a range of similar functions. These functions are essential when processing data, they have an equivalent in the ES5 specification, and they are: each, map, and reduce.

Underscore each

In the first example, we used the ES5 function Array.prototype.forEach to iterate the initial dataset. Underscore also provides its own version called _.each(). The main difference from the Array.prototype.forEach function is that _.each() can be used against object properties if an object rather than array is provided as its first argument. The full function signature is _.each(list, iteratee, [context]) and it will call the second function parameter iteratee against each item of the iterated list object or array passed as its first argument. To use this function in the second example starter-example-with-underscore.find from this chapter, we just need to replace this line from the getBicyclesCountPerType() function:

bicycles.forEach(function(bicycle) {

With line:

_.each(bicycles, function(bicycle) {

Underscore each has a forEach alias, so it can be called in a similar way with its ES5 equivalent:

_.forEach(bicycles, function(bicycle) {

Another difference from the ES5 equivalent is that Underscore each returns the first parameter as opposed to undefined allowing further function call chaining. Underscore also has first class support for function chaining that will be detailed in Chapter 4, Programming Paradigms with Underscore.js.

We will explore calling each over object properties together with other Underscore functions mentioned in this chapter in Chapter 2, Using Underscore.js with Collections.

Underscore map and reduce

The next Underscore functions of special interest are map and reduce. The Underscore map function signature is similar to the each function signature: _.map(list, iteratee, [context]). It transforms a list array or object parameter into a new array that contains modified elements or property values of the list parameter. The transformation is made by:

  • Iterating the elements or properties of the list parameter using the second parameter function iterate, and calling this function for each item;

  • Collecting the values of the iteratee call into the array returned by the _.map() function.

Underscore reduce is a function that converts an array or object properties into a single value. The function signature is _.reduce(list, iteratee, [memo], [context]) and the optional memo parameter is used as the seed for the returned value. If memo is not specified, then the first element or object property value of the list parameter will be used as the seed value instead. The iteratee function signature is iteratee(memo, element, index, list) when list is an array like object. The value returned by iteratee is either supplied as the memo parameter for the next iteration or is returned as the final reduce value if there are no more iterations left.

The next example will showcase these two functions by iterating over an array of people that have received an important award at some point in their lives—the Nobel prize for literature. The example calculates the age when the award was received using _.map() and the average value of the age when the award was received using _.reduce().

This is the initial dataset:

var people = [{
    name: "Herta Muller",
    birthYear: 1953,
    awardYear: 2009
  }, {
    name: "Mario Vargas Llosa",
    birthYear: 1936,
    awardYear: 2010
  }, {
    name: "Tomas Transtromer",
    birthYear: 1931,
    awardYear: 2011
  }, {
    name: "Mo Yan",
    birthYear: 1955,
    awardYear: 2012
  }, {
    name: "Alice Munro",
    birthYear: 1931,
    awardYear: 2013
  }, {
    name: "Patrick Modiano",
    birthYear: 1945,
    awardYear: 2014
  }];

First, we calculate the age when the award was received for each person by using _.map():

var peopleWithAwardAge = _.map(people, function(person){
  return {
    name: person.name,
    awardAge: person.awardYear - person.birthYear
  }
});

Next, we calculate the average age of the award by using _.reduce() and passing 0 as the memo seed value:

var totalAge = _.reduce(peopleWithAwardAge, function(memo, person) {
  return memo + person.awardAge;
}, 0);
var averageAwardAge = totalAge / peopleWithAwardAge.length;

You can explore the complete example in the underscore.map.reduce folder from the source code for this chapter or by running it directly at http://bit.ly/1MMSOlc.