Lodash vs Underscore
Two JavaScript utility libraries that solved the same problem in 2012. One kept shipping; the other got embalmed. The verdict isn't close.
The short answer
Lodash over Underscore for most cases. Lodash is a superset of Underscore that's faster, better documented, modular, and actively maintained.
- Pick Lodash if need utility functions in any non-trivial codebase — deep clones, debounce/throttle, chained data transforms, safe property access via _.get. Lodash is the default and the per-method imports keep your bundle honest
- Pick Underscore if maintaining a legacy Backbone app that already depends on it, or you want the smallest possible footprint and only need three functions. Otherwise, don't reach for it new
- Also consider: If you're on modern JS, you may not need either — Array.prototype methods, structuredClone, and Object spread cover a lot. Reach for Lodash only when native gets verbose.
— Nice Pick, opinionated tool recommendations
The verdict
Lodash. This isn't a debate, it's a postmortem. Lodash started in 2012 as a drop-in Underscore replacement that fixed Underscore's performance problems and edge-case bugs, then it kept going for a decade while Underscore mostly stood still. Today Lodash pulls tens of millions of weekly downloads and Underscore trails far behind, coasting on Backbone's corpse and ancient transitive dependencies. Anyone choosing Underscore for a greenfield project in this decade is either nostalgic or hasn't looked at the npm graph. The API surfaces overlap almost completely, so there's no muscle-memory cost to switching. Lodash gives you everything Underscore does, plus deep clone, _.get for safe nested access, consistent iteratee shorthands, and method chaining that doesn't surprise you. Underscore's argument order on iteratees was famously backwards from Lodash's, which is exactly the kind of papercut that made people switch in the first place. Pick Lodash and stop thinking about it.
Performance and correctness
This is where Underscore lost the original fight. Lodash was literally created because Underscore's implementations were slower and its handling of sparse arrays, array-likes, and edge cases was inconsistent. Lodash rewrote the hot paths — lazy evaluation in chains means _.chain(arr).filter().map().take(5).value() short-circuits instead of building intermediate arrays for the whole collection. Underscore evaluates eagerly and allocates the full intermediate every step. On large collections that's a real difference, not a microbenchmark fetish. Lodash also handles deep equality (_.isEqual), deep cloning (_.cloneDeep), and nested path access correctly and consistently; Underscore either lacks these or implements them shallowly. Correctness-wise, Lodash's iteratee shorthands (_.map(users, 'name'), _.filter(data, {active: true})) behave predictably across every collection method. Underscore's coverage is patchier and its method set smaller. If you've ever been burned by a shallow clone mutating shared state, Lodash already shipped the fix years ago.
Bundle size and modularity
The one place Underscore could brag is raw size — it's smaller as a monolith. But that framing is a decade out of date. Lodash ships per-method packages and supports tree-shaking through lodash-es, so you import _.debounce or _.get and pay for exactly that, not the whole 70KB kitchen sink. Done right, a modern Lodash footprint is competitive with or smaller than pulling Underscore wholesale, because nobody uses all of Underscore either. The trap is import _ from 'lodash' in a bundle that doesn't tree-shake — that drags the entire library in, and that's a you-problem, not a Lodash problem. Use lodash-es with a real bundler, or import the specific function. Underscore's smaller core stops mattering the moment you need a function it doesn't have and you reach for a second dependency anyway. One well-maintained, granular library beats a small one you outgrow in a sprint.
Maintenance and ecosystem
Maintenance is the quiet killer here. Lodash is one of the most-depended-upon packages on npm, with broad tooling support, TypeScript types via @types/lodash that are genuinely good, ESLint plugins, and documentation that actually shows examples for every method. Underscore is maintained but glacial — it had a long stretch where it barely moved, and its relevance now is mostly inertia from Backbone-era apps that can't be bothered to migrate. When you Google a Lodash method you get an answer in seconds; the community memory is enormous. TypeScript users especially should not pick Underscore — the typing experience is thinner and the function signatures less ergonomic. The honest 2026 footnote: a lot of what both libraries offered is now native JavaScript, so the real competition isn't Underscore, it's the standard library. But if you're adding a utility dependency at all, add the one with momentum. That's Lodash, and it has been for years.
Quick Comparison
| Factor | Lodash | Underscore |
|---|---|---|
| Maintenance & adoption | Tens of millions of weekly downloads, actively maintained, huge ecosystem | Trailing downloads, slow release cadence, coasting on Backbone legacy |
| Performance | Lazy evaluation in chains, optimized hot paths | Eager evaluation, allocates full intermediates |
| Feature coverage | Superset: cloneDeep, _.get, isEqual, consistent shorthands | Smaller set, shallow clone, missing safe path access |
| Bundle size (monolith) | Larger as a single import, but per-method/lodash-es tree-shakes | Smaller core monolith |
| TypeScript experience | Strong @types/lodash, ergonomic signatures | Thinner types, less ergonomic |
The Verdict
Use Lodash if: You need utility functions in any non-trivial codebase — deep clones, debounce/throttle, chained data transforms, safe property access via _.get. Lodash is the default and the per-method imports keep your bundle honest.
Use Underscore if: You're maintaining a legacy Backbone app that already depends on it, or you want the smallest possible footprint and only need three functions. Otherwise, don't reach for it new.
Consider: If you're on modern JS, you may not need either — Array.prototype methods, structuredClone, and Object spread cover a lot. Reach for Lodash only when native gets verbose.
Lodash vs Underscore: FAQ
Is Lodash or Underscore better?
Lodash is the Nice Pick. Lodash is a superset of Underscore that's faster, better documented, modular, and actively maintained. Underscore's biggest contribution to the ecosystem was inspiring Lodash to replace it.
When should you use Lodash?
You need utility functions in any non-trivial codebase — deep clones, debounce/throttle, chained data transforms, safe property access via _.get. Lodash is the default and the per-method imports keep your bundle honest.
When should you use Underscore?
You're maintaining a legacy Backbone app that already depends on it, or you want the smallest possible footprint and only need three functions. Otherwise, don't reach for it new.
What's the main difference between Lodash and Underscore?
Two JavaScript utility libraries that solved the same problem in 2012. One kept shipping; the other got embalmed. The verdict isn't close.
How do Lodash and Underscore compare on maintenance & adoption?
Lodash: Tens of millions of weekly downloads, actively maintained, huge ecosystem. Underscore: Trailing downloads, slow release cadence, coasting on Backbone legacy. Lodash wins here.
Are there alternatives to consider beyond Lodash and Underscore?
If you're on modern JS, you may not need either — Array.prototype methods, structuredClone, and Object spread cover a lot. Reach for Lodash only when native gets verbose.
Lodash is a superset of Underscore that's faster, better documented, modular, and actively maintained. Underscore's biggest contribution to the ecosystem was inspiring Lodash to replace it.
Related Comparisons
Disagree? nice@nicepick.dev