DEV Community

Ali Sherief
Ali Sherief

Posted on

A Lodash Reference But With My Preferred Methods

In most programming languages, there is a library of utility functions that compliment the basic operations and built-in functions in those languages. Some languages even have a large and well known community-supported library of useful functions that developers use commonly. Lodash is one such library for Javascript.

Lodash's focus is on functional programming. Lodash takes several common operations in Javascript and makes them available in a functional programming form. The result is that code is shorter and more compact. But this is not the only functionality Lodash provides. It also has string manipulation, math, and list/array functions.

I admit I am kind of weak in functional programming so in this article I didn't cover all of the functional programming functions but I did cover the ones that resemble normal functions, in other words the ones I like, so don't mind me. ๐Ÿ˜…

Lodash was influenced by Underscore.js, which in turn was influenced by Prototype.js, both utility libraries like Lodash. Many of the Underscore.js developers are now maintaining Lodash so this library is updated more offten than Underscore. (Prototype.js is a massively used library that according to Wikipedia is used by 2.2% of all websites and provides a couple widely needed convenience functions. I might cover that library in a future post.)

Installation

Alright so let's get to obtaining this library. It is available as both a browser script and an NPM module. The NPM module can be installed with npm or yarn in the usual way:

npm install --save lodash
Enter fullscreen mode Exit fullscreen mode

And imported using var _ = require('lodash');. The browser script can be included in HTML with <script src="lodash.js"></script>.

That's it! Now you have the entire Lodash library at your fingertips.

Special attention however needs to be given at importing from Node. In the Node version of Lodash, you are able to import only part of the module. From their site, these are the different parts you can import:

// Load the full build.
var _ = require('lodash');
// Load the core build.
var _ = require('lodash/core');
// Load the FP build for immutable auto-curried iteratee-first data-last methods.
var fp = require('lodash/fp');

// Load method categories.
var array = require('lodash/array');
var object = require('lodash/fp/object');

// Cherry-pick methods for smaller browserify/rollup/webpack bundles.
var at = require('lodash/at');
var curryN = require('lodash/fp/curryN');
Enter fullscreen mode Exit fullscreen mode

Functions

Lodash has different categories of methods and I will break them down in different sections. Obviously I won't cover all of them, only the main ones (subject to my opinion ๐Ÿ™‚)

I assume the full Lodash library has been imported to variable _. The underscore is part of the reason the library is named "Lodash", because it is usually imported to this variable. Arguably the official documentation presents these function in the most accessible form but it doesn't hurt to have it in different places.

Array Functions

_.chunk(array, [size=1]): Splits an array into chunks

Creates an array of elements split into groups the length of size. If array can't be split evenly, the final chunk will be the remaining elements.

_.compact(array): Remove false values from an array

Creates an array with all falsey values removed. The values false, null, 0, "", undefined, and NaN are falsey.

_.concat(array, [values]): Concatenate arrays

Creates a new array concatenating array with any additional arrays and/or values.

_.drop(array, [n=1]): Remove array elements from the beginning

Creates a slice of array with n elements dropped from the beginning.

_.dropRight(array, [n=1]): Remove array elements from the end

Creates a slice of array with n elements dropped from the end.

_.flattenDeep(array): Flattens nested arrays

Recursively flattens array.

_.reverse(array): Reverses an array

Reverses array so that the first element becomes the last, the second element becomes the second to last, and so on.

Note: This method mutates array and is based on Array#reverse.

_.slice(array, [start=0], [end=array.length]): Create a slice of an array

Creates a slice of array from start up to, but not including, end.

Note: This method is used instead of Array#slice to ensure dense arrays are returned.

_.uniq(array): Create a copy of arrays without duplicate values

Creates a duplicate-free version of an array, using SameValueZero for equality comparisons, in which only the first occurrence of each element is kept. The order of result values is determined by the order they occur in the array.

_.without(array, [values]): Filter values out of an array

Creates an array excluding all given values using SameValueZero for equality comparisons.

Collection Functions

A reminder, a collection is a sequence of items, it could also be an array. Arrays guarrentee the items will be iterated in order, whereas if the collection is a set, it will be iterated in a random order.

_.forEach(collection, [iteratee=_.identity]): Call a function for each collection.

Iterates over elements of collection and invokes iteratee for each element. The iteratee is invoked with three arguments: (value, index|key, collection). Iteratee functions may exit iteration early by explicitly returning false.

_.every(collection, [predicate=_.identity]): Tests if an expression is true for all collection elements

Checks if predicate returns truthy for all elements of collection. Iteration is stopped once predicate returns falsey. The predicate is invoked with three arguments: (value, index|key, collection).

Note: This method returns true for empty collections because everything is true of elements of empty collections.

_.some(collection, [predicate=_.identity]): Tests if an expression is true for any of the collection elements

Checks if predicate returns truthy for any element of collection. Iteration is stopped once predicate returns truthy. The predicate is invoked with three arguments: (value, index|key, collection).

_.filter(collection, [predicate=_.identity]): Return a new collection with items not matching a predicate expression filtered out

Iterates over elements of collection, returning an array of all elements predicate returns truthy for. The predicate is invoked with three arguments: (value, index|key, collection).

_.find(collection, [predicate=_.identity], [fromIndex=0]): Return the index of the first collection item that matches a predicate expression.

Iterates over elements of collection, returning the first element predicate returns truthy for. The predicate is invoked with three arguments: (value, index|key, collection).

_.includes(collection, value, [fromIndex=0]): Checks if an item is in a collection.

Checks if value is in collection. If collection is a string, it's checked for a substring of value, otherwise SameValueZero is used for equality comparisons. If fromIndex is negative, it's used as the offset from the end of collection.

_.sample(collection): Get a random element from a collection

Gets a random element from collection.

_.sampleSize(collection, [n=1]): Get n random elements from a collection

Gets n random elements at unique keys from collection up to the size of collection.

_.shuffle(collection): Returns a collection of shuffled elements in the original collection

Creates an array of shuffled values, using a version of the Fisher-Yates shuffle.

Math Functions

We have add, ceil, divide, floor, max, mean, min, multiply, round, subtract and sum functions, which do what you'd expect them to o if you are versed in mathematics. These need no introduction in my opinon.

Date Functions

There is only one method in this category and that is now.

_.now(): Return current time in milliseconds since epoch

Gets the timestamp of the number of milliseconds that have elapsed since the Unix epoch (1 January 1970 00:00:00 UTC).

Functional Methods

_.after(n, func): Calls func once the function after returns is called n or more times.

This method creates a function that invokes func once it's called n or more times.

Example:

var saves = ['profile', 'settings'];

var done = _.after(saves.length, function() {
  console.log('done saving!');
});

_.forEach(saves, function(type) {
  asyncSave({ 'type': type, 'complete': done });
});
// => Logs 'done saving!' after the two async saves have completed.
Enter fullscreen mode Exit fullscreen mode

_.bind(func, thisArg, [partials]): Creates a function that is bound to an object thisArg. The partials are a list of arguments to apply to it. Some of the partials can have the placeholder value _ (the Lodash imported var) to skip applying some arguments. You can use it to apply the arguments after a certain number while calling the bind()ed function with the ones you did not bind.

Creates a function that invokes func with the this binding of thisArg and partials prepended to the arguments it receives.

The _.bind.placeholder value, which defaults to _ in monolithic builds, may be used as a placeholder for partially applied arguments.

Note: Unlike native Function#bind, this method doesn't set the "length" property of bound functions.

function greet(greeting, punctuation) {
  return greeting + ' ' + this.user + punctuation;
}

var object = { 'user': 'fred' };

var bound = _.bind(greet, object, 'hi');
bound('!');
// => 'hi fred!'

// Bound with placeholders.
var bound = _.bind(greet, object, _, '!');
bound('hi');
// => 'hi fred!'
Enter fullscreen mode Exit fullscreen mode

_.debounce(func, [wait=0], [options={}]): Creates a function that calls func and delays for wait milliseconds between calls.

Creates a debounced function that delays invoking func until after wait milliseconds have elapsed since the last time the debounced function was invoked. The debounced function comes with a cancel method to cancel delayed func invocations and a flush method to immediately invoke them.

_.delay(func, wait, [args]): Call func after wait milliseconds.

Invokes func after wait milliseconds. Any additional arguments are provided to func when it's invoked.

_.memoize(func, [resolver]): Saves the result of func to the cache inside the returned variable (memoizes the result, also known as caching it so that the result from cache is used When the returned function is called instead of invoking func a second time).

In Javascript you can have a function variable but having arbitrary properties with Object values, that's the variable returned by memoize.

Creates a function that memoizes the result of func. If resolver is provided, it determines the cache key for storing the result based on the arguments provided to the memoized function. By default, the first argument provided to the memoized function is used as the map cache key. The func is invoked with the this binding of the memoized function.

_.throttle(func, [wait=0], [options={}]): Returns a function based on func that limits execution to once every wait milliseconds.

I wish I knew about this earlier. It would have been very helpful for my earlier Javascript doesn't sleep post.

To my understanding, the difference between this and debounce is that debounce will queue each execution of func until the wait time has passed, so you end up with a lot of calls to func happening simultaneously. Whereas this function discards the call entirely if the wait time hasn't passed yet. There is also a helpful article that explains the difference between the two called Debouncing and Throttling Explained Through Examples, so be sure to check that out as well.

And we're done

If you see any errors in this post, please let me know so I can correct them.


Sources:
https://lodash.com/docs/4.17.15

Discussion (0)