DEV Community

hjqueeen
hjqueeen

Posted on

Underscore.js and ES6

Underscore.js is a JavaScript library that provides a whole mess of useful functional programming helpers without extending any built-in objects. It was first released in 2009 by Jeremy Ashkenas, who is also known for creating Backbone.js and CoffeeScript. Underscore.js offers utility functions for common programming tasks, including manipulating arrays, objects, and functions.

As for its current usage, while Underscore.js was extremely popular in the early 2010s for its utility functions, the landscape of JavaScript has evolved significantly since then. Many features that were once only available through libraries like Underscore.js have been incorporated into the ECMAScript standard, making these libraries less essential for modern development. For example, ES6 (ECMAScript 2015) introduced a slew of new features, including arrow functions, promises, and template literals, as well as new methods for arrays and objects that replicate much of the functionality provided by Underscore.js.

Today, while Underscore.js is not as widely used as it once was, it remains a valuable resource for projects that require compatibility with older browsers or that already have a dependency on it. Developers might also prefer it for its concise API and functional programming style in specific scenarios. However, for most modern JavaScript development, native ES6+ features and other libraries or frameworks like Lodash (a similar library that offers more features and better performance in some cases) or functional programming libraries such as Ramda may be more commonly recommended.

Let's explore a comprehensive list of Underscore.js functionalities that have been integrated into ES6 (ECMAScript 2015) and beyond, providing examples of both Underscore.js and their native JavaScript counterparts.

Only in Underscore.js

1. bindAll

The bindAll function in Underscore.js is used to permanently bind one or more methods of an object to the object itself. This is particularly useful for ensuring that the this context within methods accurately points to the object, especially when methods are passed as callbacks or used as event handlers. By using bindAll, you can ensure that this within the methods always refers to the specified object, preventing this from referring to a different context.

_.bindAll(object, methodNames...)
Enter fullscreen mode Exit fullscreen mode

object: The object whose methods' this context you want to bind.
methodNames: One or more method names to bind. Each name is specified as a string. You can list multiple method names separated by commas.

var obj = {
  name: 'Underscore.js',
  greet: function() {
    console.log("Hello from " + this.name);
  },
  farewell: function() {
    console.log("Goodbye from " + this.name);
  }
};

// Bind the greet and farewell methods to the obj object
_.bindAll(obj, 'greet', 'farewell');

setTimeout(obj.greet, 1000); // Outputs "Hello from Underscore.js"
setTimeout(obj.farewell, 1000); // Outputs "Goodbye from Underscore.js"
Enter fullscreen mode Exit fullscreen mode

In this example, when obj.greet and obj.farewell are called using setTimeout, _.bindAll ensures these methods are correctly bound to the obj object, allowing this.name to correctly reference the object's name property.

More : bindAll

2. wrap

The purpose of wrap is to take an existing function and a wrapper function, and return a new function that, when called, calls the wrapper function with the original function passed as the first argument, followed by any arguments passed to the new function.

Syntax:

_.wrap(function, wrapper)
Enter fullscreen mode Exit fullscreen mode

function: The original function to wrap.
wrapper: The function that will wrap the original function. The first argument to the wrapper will be the original function.

Example:

var greet = function(name) { return "hello: " + name; };
var shout = _.wrap(greet, function(func) {
  return func().toUpperCase() + "!";
});

shout('moe');
// => "HELLO: MOE!"
Enter fullscreen mode Exit fullscreen mode

In this example, shout is a new function that wraps greet with additional functionality (converting the greeting to uppercase and appending an exclamation mark).

More : wrap

3. _.mixin(object)

Allows you to extend Underscore with your own utility functions. Pass a hash of {name: function} definitions to have your functions added to the Underscore object, as well as the OOP wrapper. Returns the Underscore object to facilitate chaining.

_.mixin({
  capitalize: function(string) {
    return string.charAt(0).toUpperCase() + string.substring(1).toLowerCase();
  }
});
_("fabio").capitalize();
=> "Fabio"
Enter fullscreen mode Exit fullscreen mode

4. _.template

Compiles JavaScript templates into functions that can be evaluated for rendering. Useful for rendering complicated bits of HTML from JSON data sources. Template functions can both interpolate values, using <%= … %>, as well as execute arbitrary JavaScript code, with <% … %>. If you wish to interpolate a value, and have it be HTML-escaped, use <%- … %>. When you evaluate a template function, pass in a data object that has properties corresponding to the template's free variables. The settings argument should be a hash containing any _.templateSettings that should be overridden.

var compiled = _.template("hello: <%= name %>");
compiled({name: 'moe'});
=> "hello: moe"

var template = _.template("<b><%- value %></b>");
template({value: '<script>'});
=> "<b>&lt;script&gt;</b>"
Enter fullscreen mode Exit fullscreen mode

You can also use print from within JavaScript code. This is sometimes more convenient than using <%= ... %>.

var compiled = _.template("<% print('Hello ' + epithet); %>");
compiled({epithet: "stooge"});
=> "Hello stooge"
Enter fullscreen mode Exit fullscreen mode

Similar Funktion in Underscore.js and ES6

_.isUndefined
Returns true if value is undefined.

_.isUndefined(window.missingVariable);
=> true
Enter fullscreen mode Exit fullscreen mode

_.keys
Retrieve all the names of the object's own enumerable properties.

_.keys({one: 1, two: 2, three: 3});
=> ["one", "two", "three"]
Enter fullscreen mode Exit fullscreen mode

_.isFunction
_.find
_.has
_.defaults
_.isEmpty
_.last
_.first
_.isArray
_.size
_.each
_.rtoken
_.set

Array Methods

  • _.each / _.forEach
Underscore.js: _.each([1, 2, 3], alert);
ES6: [1, 2, 3].forEach(alert);
Enter fullscreen mode Exit fullscreen mode
  • _.map
Underscore.js: _.map([1, 2, 3], function(num) { return num * 3; });
ES6: [1, 2, 3].map(num => num * 3);
Enter fullscreen mode Exit fullscreen mode
  • _.filter
Underscore.js: _.filter([1, 2, 3, 4, 5], function(num) { return num % 2 === 0; });
ES6: [1, 2, 3, 4, 5].filter(num => num % 2 === 0);
Enter fullscreen mode Exit fullscreen mode
  • _.find
Underscore.js: _.find([1, 2, 3, 4, 5], function(num) { return num % 2 === 0; });
ES6: [1, 2, 3, 4, 5].find(num => num % 2 === 0);
Enter fullscreen mode Exit fullscreen mode
  • _.reduce
Underscore.js: _.reduce([1, 2, 3], function(memo, num) { return memo + num; }, 0);
ES6: [1, 2, 3].reduce((memo, num) => memo + num, 0);

Enter fullscreen mode Exit fullscreen mode
  • _.every
Underscore.js: _.every([2, 4, 6], function(num) { return num % 2 === 0; });
ES6: [2, 4, 6].every(num => num % 2 === 0);
Enter fullscreen mode Exit fullscreen mode
  • _.some
Underscore.js: _.some([2, 4, 5], function(num) { return num % 2 === 0; });
ES6: [2, 4, 5].some(num => num % 2 === 0);
Enter fullscreen mode Exit fullscreen mode

Object Methods

  • _.keys
Underscore.js: _.keys({one: 1, two: 2, three: 3});
ES6: Object.keys({one: 1, two: 2, three: 3});
Enter fullscreen mode Exit fullscreen mode
  • _.values
Underscore.js: _.values({one: 1, two: 2, three: 3});
ES6: Object.values({one: 1, two: 2, three: 3});
Enter fullscreen mode Exit fullscreen mode
  • _.extend / Object.assign
Underscore.js: _.extend({name: 'Moe'}, {age: 50});
ES6: Object.assign({name: 'Moe'}, {age: 50});
Enter fullscreen mode Exit fullscreen mode

Utility Methods

  • _.range
Underscore.js: _.range(10);
ES6: Array.from({length: 10}, (v, k) => k);
Alternative ES6: [...Array(10).keys()];
Enter fullscreen mode Exit fullscreen mode

Function Methods

While ES6 does not directly replace all function utilities from Underscore.js like _.debounce or _.throttle, newer JavaScript environments and libraries often provide similar functionalities, and developers can implement these patterns using native JavaScript or newer web APIs.

More Informations: You-Dont-Need-Lodash-Underscore

Top comments (0)