Luke M
Lodash notes
2025-02-24
Comparison to JavaScript ES6
For most of my career, I've stuck with Javascript ES6 Array.prototype patterns for manipulating collections. These are for the most part, good enough.
However, there are some benefits to using Lodash; it performs much better with very high amounts of records, and its syntax can be more idiomatic.
Turn a record into an array
I prefer to use Lodash with the _.chain
function so that the syntax is similar
to JS ES6 collection methods that I'm used to.
// ES6
Object.values(data);
// Lodash
_.chain(data).values().value();
Implicit vs explicit chaining
A newer syntax allows the chain
function to be implied, and the .value()
to be dropped from the end.
Explicit chaining with _.chain(...)
_.chain([]).uniq().sum().value();
Implicit chaining with _(data)
- Implicit chaining creates a Lodash wrapper object which must be unwrapped
- A chain-breaking method like
sum()
,max()
, orfind()
unwraps the value automatically, therefore.value()
can be omitted. - A chainable method like
uniq()
,map()
,filter()
returns a wrapped value, and.value()
is required to extract it.
_(data).uniq().sum(); // Does not return a collection therefore omit .value()
_(data).uniq().value(); // Returns a collection, therefore requires .value()
While both chaining styles use identical lazy logic, and the difference is purely
syntactic, it is recommended to use _(data)
(implicit chaining) because it has
cleaner syntax and is more idiomatic.
Lazy-evaluation
By default, Lodash will attempt to use lazy evaluation.
Lazy evaluation uses these techniques to reduce the amount of iterations in an enumeration:
- Pipelining: Applies all operations per element in a single pass.
- Short-circuiting: Some methods like
take()
stop iteration early.
This results in much better performance on large collections.
There are certain functions that are incompatible with lazy-evaluation- if you
use them, the lazy evaluation will be stopped, and eager evaluation used
instead. Examples include sortBy()
, reverse()
, each()
, forEach()
, head()
,
and last()
.
Debugging Lodash
The Lodash tap
method calls a function on the collection, without affecting
it. It is extremely useful for debugging, because you can move the
_.tap(console.log)
to any point in your Lodash chain to inspect it.
// ES6
data.forEach((x) => {
console.log(x);
return x;
});
// Lodash
_.chain(data).tap(console.log).value();
Sorting
One reason to use Lodash is that ES6's sort()
mutates the original array, while Lodash's sortBy
and orderBy
return a new sorted array.
Sorting by date
The use of JavaScript's
Date
object is the fastest way to blood on the floor.
There are several problems with it; such as performance when working with large datasets, no timezone, and the fact that Dates are mutable (so any arithmetic performed on them permanently changes them).
For this reason, when sorting dates, I'm always sorting a string. Because sort works on alphanumeric values, sorting by date is usually as easy as sorting the strings.
Sort by date
// ES6
date.sort((a, b) => b.date.localeCompare(a.date));
// Lodash
_.chain(data).orderBy("date").value();
Sort by optional date
// ES6
data.sort((a, b) => {
const dateA = a.date || "";
const dateB = b.date || "";
return dateB.localeCompare(dateA);
});
// Lodash
_.chain(data)
.sortBy((x) => x.date || "")
.reverse()
.value();
Filtering
Filter out null values
The _.compact()
function can be used to remove nullish values from the
collection.
_(data).compact();
Filter out expired dates
// Lodash
_.chain(data).filter((x) => !x.date || x.date > new Date().toISOString());