Introduction to Underscore.js: Simplify web development with Powerful Utility Functions

What is Underscore.js ?

Underscore.js is a popular JavaScript library that provides utility functions for common programming tasks. It is commonly used in web development to simplify and enhance the manipulation of arrays, objects, functions, and other data structures.

Underscore.js offers a wide range of functions that help with tasks such as iterating over collections, filtering data, mapping data, reducing arrays, and much more. It provides functional programming utilities that promote a more functional and concise coding style.

Utility functions categories

In the context of Underscore.js, “utility functions” specifically refers to the functions provided by the Underscore.js library. Based on functionality, there are primarily six categories:

  1. Collection Functions: These functions operate on arrays and objects, allowing you to manipulate, iterate, filter, group, and transform collections of data. Some examples of collection functions are each, map, reduce, filter, groupBy, sortBy, countBy, and shuffle.
  2. Array Functions: These functions specifically target operations on arrays. They include methods like first, last, compact, flatten, union, intersection, and without.
  3. Object Functions: These functions work with JavaScript objects. They include utilities like keys, values, extend, pick, omit, and defaults.
  4. Function Functions: These functions deal with JavaScript functions, allowing you to manipulate and manage function execution. Some examples include bind, throttle, debounce, once, and wrap.
  5. Utility Functions: This category includes general-purpose utilities like identity, constant, noop, and uniqueId.
  6. Chaining: Underscore.js supports method chaining, allowing you to chain multiple function calls together to create more complex operations on data.

What are the different ways of accessing functions in Underscore.js?

There are several ways to access and use its utility functions in Underscore.js. You can typically use the “_" (underscore) global object, which serves as the namespace ( a container or scope that holds a set of related functions, classes, variables, or other identifiers )  for all Underscore.js utility functions. The primary ways of accessing functions in Underscore.js are:

  1. Directly via "_": Most commonly, you access functions directly from the "_" global object. For example, to use the map function to transform an array, you would write :
 _.map(array, iteratee)
  1. Importing Specific Functions (ES6): If you are using modern JavaScript (ES6 or later) and prefer to import specific functions rather than accessing them via the "_" object, you can use named imports. 
import { map, filter, reduce } from 'underscore';

After importing the specific functions, you can use them directly in your code, like 

 map(array, iteratee)
  1. Using Method Chaining: Underscore.js supports method chaining, which allows you to chain multiple function calls together. To use method chaining, simply call a function on the "_" object, and it will return a wrapped object that allows you to chain subsequent function calls.
    const numbers = [1, 2, 3, 4, 5];
    
    const result = _.chain(numbers).map((num) => num * 2).filter((num) => num > 5).value();
    
    console.log(result); // Output: [6, 8, 10]

    In the above example, _.chain(numbers) creates a wrapped object, and you can chain map and filter functions to perform multiple operations on the data.

    1. Adding _ as a Variable Alias: In some cases, you might see developers using "_" as an alias for the “_.” object to simplify function calls. However, this practice is NOT recommended, as it can lead to potential conflicts with other libraries or native JavaScript features.

    The most common approach is to access functions directly from the _ global object, as this aligns with the conventional usage of Underscore.js.

    Accessing underscore.js function with global object

    In Underscore.js, functions are typically invoked through the global "_" object, which serves as a namespace for all the utility functions provided by the library. The syntax for using functions in Underscore.js is straightforward and consistent across most of its utility functions.

    Here’s the general syntax for using functions in Underscore.js:

    _.functionName(list, [iteratee], [context]);

    Let’s break down the components:

    TermDescription
    _The underscore character followed by the global object _, which acts as the namespace for all Underscore.js utility functions.
    functionNameThe name of the specific utility function you want to use. Examples include each, map, reduce, filter, and many others.
    listThe array or object that you want to work with. This is the data you want to iterate over or manipulate using the specific function.
    iteratee(optional) A function that defines the transformation, test, or operation you want to perform on each element in the list. Depending on the function, the iteratee may be optional or required.
    context(optional) The context (this) to be used as the reference for the iteratee function. This argument is only required for certain functions and can often be omitted.

    let’s look at an example.

    // Sample array of people objects, each containing a 'name' and 'age' property
    
    const people = [
      { name: 'Alice', age: 25 },
      { name: 'Bob', age: 30 },
      { name: 'Charlie', age: 22 },
      { name: 'Diana', age: 28 },
    ];
    
    // Define the iteratee function to filter out people below the age threshold stored in 'this.ageThreshold'
    
    function iteratee(person) {
      if (person.age >= this.ageThreshold) {
        return person;
      }
    }
    
    // Create a context object that stores the age threshold value
    
    const context = {
      ageThreshold: 25,
    };
    
    // Using Underscore's map function with all parameters, and passing the context
    
    const filteredPeople = _.map(people, iteratee, context);
    console.log(filteredPeople);
    
    // Output: [{ name: 'Alice', age: 25 }, { name: 'Bob', age: 30 }, { name: 'Diana', age: 28 }]

    In this example, we used the context parameter to store the age threshold value of 25. The iteratee function now filters out people from the people array who are younger than or equal to the age threshold. By using this.ageThreshold in the iteratee function, we can access the age threshold value stored in the context object.

    The use of the context parameter becomes relevant in this scenario because it allows us to pass additional data (the age threshold) to the iteratee function without having to explicitly pass it as an argument to the function. This can be especially useful when you have multiple functions that need to share the same contextual information.

    How to integrate Underscore.js into your project

    Using Downloads

    You can download the underscore.js from the official document and use it in your project

    <!doctype html>
    <html lang="en">
      <head>
        <meta charset="UTF-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    
        <script type="text/javascript" src="./underscore-umd-min.js"></script>
        <title>Demo App</title>
      </head>
      <body>
        <div id="demo"></div>
        <script>   
            const numbers = [1, 2, 3, 4, 5];
            const doubledNumbers = _.map(numbers, (num) => num * 2);
            document.getElementById("demo").innerHTML =  doubledNumbers;
        </script>
      </body>
    </html>

    Using CDN URLs 

    Use a Content Delivery Network (CDN) to include Underscore.js directly in your project without downloading it.

    There are two types of min.js files: The UMD( Universal Module Definition ) and the ESM( ECMAScript Module ) formats.

    The UMD format allows the Underscore.js library to be used in various environments, making it more versatile and compatible with different module systems and environments.

    Therefore, you can use the UMD format in the way you traditionally use CDN URLs with the <script></script> tags.

    <!doctype html>
    <html lang="en">
      <head>
        <meta charset="UTF-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <script type="text/javascript" src="https://cdn.jsdelivr.net/npm/[email protected]/underscore-umd-min.js"></script>
        <title>Demo App</title>
      </head>
      <body>
        <div id="demo"></div>
        <script>   
          const numbers = [1, 2, 3, 4, 5];
          const doubledNumbers = _.map(numbers, (num) => num * 2);
          document.getElementById("demo").innerHTML =  doubledNumbers;  
        </script>
      </body>
    </html>

    ESM format is specifically designed for modern JavaScript environments that support ES6 modules, such as modern web browsers and build tools like Webpack and Rollup. This format of Underscore.js is intended for use in modern JavaScript projects that take advantage of ES6 modules. When you use the ESM format, you need to some modifications to your code.

    <!DOCTYPE html>
    <html>
    <head>
      <title>Demo App</title>
    </head>
    <body>
      <div id="demo"></div>
    
      <script type="module">   
        import { map } from 'https://cdn.jsdelivr.net/npm/[email protected]/underscore-esm-min.js';
    
        const numbers = [1, 2, 3, 4, 5];
        const doubledNumbers = map(numbers, (num) => num * 2);
        document.getElementById("demo").innerHTML =  doubledNumbers;
    
      </script>
    </body>
    </html>

    When you use the ESM format in the development settings, you need to make sure you run your project on a live web server. If you are in VS code, you can install an extension such as “Live Server” to run your project.

    How to use Underscore.js in React projects

    Just as with any web project, you can download the library and use in your React project. But, we are going to see how to use the CDN URLs in your React project.

    Using the UMD CDN URL format

    1. In your React project, locate the public folder, and within it, you’ll find the index.html file.
    2. Include Underscore.js CDN in index.html.
    <!DOCTYPE html>
    <html>
    <head>
      <title>Your React App</title>
    </head>
    <body>
      <div id="root"></div>
      <!-- Add the script tag for Underscore.js here -->
      <script src="https://cdn.jsdelivr.net/npm/underscore@latest/underscore-umd-min.js"></script>
    </body>
    </html>

    1. Use Underscore.js Functions in Your React Components:
      • Now that Underscore.js is included in your project, you can use its functions in your React components.
    import React from 'react';
    
    const MyComponent = () => {
      const numbers = [1, 2, 3, 4, 5];
    
      // Using Underscore's map function to double each element
      const doubledNumbers = _.map(numbers, (num) => num * 2);
    
      return (
        <div>
          {
          //this map is not from underscore.js
          doubledNumbers.map((num) => ( 
            <p key={num}>{num}</p>
          ))}
        </div>
      );
    };
    
    export default MyComponent;

    No-undef run-time error when you use UMD CDN format

    When you use UMD CDN format as in the above example, you might encounter the following error:

    '_' is not defined  no-undef
    Search for the keywords to learn more about each error.
    ERROR in src\App.js
     '_' is not defined  no-undef

     The ‘_’ is not defined no-undef error occurs because ESLint, a popular JavaScript linter, is likely flagging the usage of the underscore character (_) as an undefined variable. This happens when you’re using Underscore.js with React without explicitly defining _ ( underscore ) as a global variable.

    There are two ways to resolve this issue:

    1. Explicitly Define “_” as a Global Variable: You can tell ESLint that _ is a global variable so that it doesn’t throw an error. 
      • Add the following comment ( /* global _ */ ) at the top of the file where you are using Underscore.js. This comment informs ESLint that “_” is a global variable and prevents the ‘_’ is not defined no-undef error.

    App.js

    /* global _ */
    
    function App() {
    
       const numbers = [1, 2, 3, 4, 5];
    
    // Using Underscore's map function to double each element
       const doubledNumbers = _.map(numbers, (num) => num * 2);
    
      return (
        <div className="App">
           {doubledNumbers.map((num) => (
            <p key={num}>{num}</p>
          ))}
        </div>
      );
    }
    
    export default App;

    1. Use window._ to Access “_"
      • If the first approach doesn’t work, you can access Underscore.js functions using window._. The window object in the browser acts as a global scope, so you can access _ through it. 
    // Sample array
    
    const numbers = [1, 2, 3, 4, 5];
    const doubledNumbers = window._.map(numbers, (num) => num * 2);
    console.log(doubledNumbers); // Output: [2, 4, 6, 8, 10]

    Using the ESM CDN URL format

    App.js

    import _ from 'https://cdn.jsdelivr.net/npm/[email protected]/underscore-esm-min.js';
    
    function App() {
       const numbers = [1, 2, 3, 4, 5];
       const doubledNumbers = _.map(numbers, (num) => num * 2);
    
      return (
        <div className="App">
           {doubledNumbers.map((num) => (
            <p key={num}>{num}</p>
          ))}
        </div>
      );
    }
    
    export default App;

    Or

    import { map } from 'https://cdn.jsdelivr.net/npm/[email protected]/underscore-esm-min.js';
    
    function App() {
    
       const numbers = [1, 2, 3, 4, 5];
       const doubledNumbers = map(numbers, (num) => num * 2);
    
      return (
        <div className="App">
           {doubledNumbers.map((num) => (
            <p key={num}>{num}</p>
          ))}
        </div>
    
      );
    }
    
    export default App;

    Install Underscore.js as a package and Import the utility functions (Recommended)

    This is the recommended way to use Underscore.js in React projects. You can import specific Underscore.js functions using ES6 import statements:

    1. First install Underscore.js library: npm install underscore
    1. Then you can add the following code in App.js
    import { map } from 'underscore';
    
    function App() {
    
       const numbers = [1, 2, 3, 4, 5];
       const doubledNumbers = map(numbers, (num) => num * 2);
    
      return (
        <div className="App">
           {doubledNumbers.map((num) => (
            <p key={num}>{num}</p>
          ))}
        </div>
    
      );
    }
    
    export default App;

    This way, you are explicitly importing the map function (or other needed functions) from the underscore module, and ESLint will not raise an error for using an undefined _.

    Conclusion

    Underscore.js is a versatile and efficient utility library for JavaScript, offering a comprehensive set of functions to handle arrays, objects, functions, and more. It enhances code readability and maintainability by providing a functional programming paradigm and streamlining common data manipulation tasks. With its broad range of utility functions, Underscore.js continues to be a valuable tool for developers, simplifying complex operations and empowering them to create robust and expressive applications.

    Leave a Comment

    Your email address will not be published. Required fields are marked *

    Scroll to Top