Let's talk about Lodash
Laurie

Laurie @laurieontech

About: Software dev at Netflix | DC techie | Conference speaker | egghead Instructor | TC39 Educators Committee | Girls Who Code Facilitator | Board game geek | @laurieontech on twitter

Joined:
Apr 12, 2018

Let's talk about Lodash

Publish Date: Jun 4 '21
150 20

If you were a JavaScript developer during a certain era, you're likely familiar with the library Lodash. It's a utility library full of functions that make it easier to manipulate arrays, objects and strings. Lodash included so many critical functions that, for a long time, it was one of the first things developers would download when setting up a new project. However, times have changed.

So let's talk about how we might think about Lodash in the context of today.

ECMAScript

For a primer on ECMAScript and TC39 I recommend reading my post on the ECMAScript Ecosystem. With that out of the way, let's talk about new features to the language.

Arrays

One of the things Lodash is known for are wonderful functions for handling arrays. For example, flattening them.

const arr = [1, [2, [3, 4]]]
_.flatten.(arr) // [1,2,[3,4]]
Enter fullscreen mode Exit fullscreen mode

We don't need to use Lodash for this anymore! Array.prototype.flat is a thing.

const arr = [1, [2, [3, 4]]]
arr.flat() // [1,2,[3,4]]
Enter fullscreen mode Exit fullscreen mode

In fact, the flat function handles all three of the Lodash flatten methods.

const arr = [1, [2, [3, 4]]]

_.flatten.(arr) // [1,2,[3,4]]
arr.flat() // [1,2,[3,4]]

_.flattenDeep.(arr) // [1,2,3,4]
arr.flat(Infinity) // [1,2,3,4]

_.flattenDepth.(arr, 2) // [1,2,3,4]
arr.flat(2) // [1,2,3,4]
Enter fullscreen mode Exit fullscreen mode

Objects

Another popular method that people reach for is Lodash's get. This one found a JS substitute a bit more recently.

const obj = { a: 1, b: { c: 3, d: 4 } }

_.get(obj, 'a.b.c') // 3
Enter fullscreen mode Exit fullscreen mode

This method helps you dive deep into objects and not worry about whether or not the values exist. As an alternative, we now have optional chaining.

const obj = { a: 1, b: { c: 3, d: 4 } }

obj.a?.b?.c // 3
Enter fullscreen mode Exit fullscreen mode

As it turns out, get takes a third parameter, a default value. To match this functionality we have nullish coalescing.

const obj = { a: 1, b: { c: 3, d: 4 } }

_.get(obj, 'a.b.e', 'default') // default

obj.a?.b?.e ?? 'default' // default
Enter fullscreen mode Exit fullscreen mode

Goodbye Lodash?

You may think that these examples mean Lodash is no more! Well, not so fast.

While ECMAScript has added a number of new features in the past few years, there are still parts of Lodash that don't have native replacements.

Some are under discussion, like the pipeline operator, which has some similarities to Lodash's chain method.

Others are still just a twinkle in JavaScript's eye. groupby and deepmerge are commonly referenced in the category of things people would like native implementations of.

So why does it matter?

You might wonder why this matters. If some things have native alternatives and others don't, why not use Lodash for everything and make your life easier?

Well, Lodash isn't exactly small. Installing it as a dependency in your project doesn't matter so much, but loading it up for every page isn't ideal. So you want to consider a couple things.

  1. If you don't have to use a Lodash dependency and can use a native solution, do so.
  2. If you've determined you need a Lodash method, don't import the entire library.

Instead of doing this:

import _ from 'lodash'
Enter fullscreen mode Exit fullscreen mode

Do something like this:

import map from 'lodash/map'
Enter fullscreen mode Exit fullscreen mode

Alternatively, there is a Babel plugin that can do this for you. There is also a webpack plugin that will further optimize things.

And that's it

Now go forth with your newfound Lodash knowledge! Make intentional choices about what needs a third-party dependency. And be sure to check out the do you need Lodash project.

Comments 20 total

  • Alex Kates
    Alex KatesJun 4, 2021

    +1 for the

    import map from 'lodash/map'

    Great tip, Laurie!

    • Vitalii Saienko
      Vitalii SaienkoJun 7, 2021

      You can also install lodash-es and then use

      import { groupBy } from 'lodash-es'
      
      Enter fullscreen mode Exit fullscreen mode

      In this case, no Babel plugins are needed, it's tree-shakable by default. And you can use regular imports.

  • Alex Lohr
    Alex LohrJun 4, 2021

    I found that helper tools like lodash, underscore, etc. tend to lend themselves to help the developer outsource complexity instead of actually understanding the underlying issue enough to reduce the complexity to a point where you get an elegant solution. While that may not always be possible, I find that not using lodash often results in better code. But if you use it, be sure to use it whenever it makes sense.

    • Eldar Shamukhamedov
      Eldar ShamukhamedovJun 5, 2021

      I've found the opposite. Folks write custom implementations of deep merge, intersection, is plain object, etc. and miss edge cases. These helpers then end up being used all over the place, which makes it very hard to fix any issues.

      For sure use native JS built-ins over Lodash, but if you're considering writing your own version of one of the more complex Lodash helpers, at least go read their source code first.

      • Alex Lohr
        Alex LohrJun 5, 2021

        That's what I mean with unnecessary complexity. There are less problems that strictly require these functions than one would think.

        Also, things like deep cloning also have issues in lodash and other tools, see github.com/atk/object-clone-propos...

        So using these tools is not a silver bullet. As I said, if you use them, make it count, but try to solve the underlying issue before you grab these tools.

      • jan paul
        jan paulJun 6, 2021

        y the deepcopy stuff is still very viable

    • Robin Schulz
      Robin SchulzJun 7, 2021

      I've been using Lodash and Underscore since their existence and have made use of them extensively! However, this changed half a year ago when I started working on a lightweight Microservice component that I build with Node.js, where every single byte counts.

      Now that I got rid of Lodash/Underscore, I basically recreated the helper functions I was using; it's even more fun to use them as I now precisely know what they're doing and with what data types I'm dealing with and ultimately no longer need to be prepared for all eventualities and types.

      P.S. I kind of agree with @lexlohr . Even for me and 20+ years of experience, I often didn't even try to understand how some of the helper functions work; I just used them and got instant results, eez.

      I can definitely recommend using one of the two libraries when starting a new project. As soon as you know which helper functions you ultimately need, you can start replacing the library helper functions with your logic using Lodash its .mixin() feature to extend core helper functions with custom ones. In this case, you want to overwrite core functions with your logic: dustinpfister.github.io/2018/01/31.... If this is done, you can replace the Lodash helper functions with your own helper functions.

      Cheers

  • Jen Chan
    Jen ChanJun 4, 2021

    Yay!!! Thanks for describing what we don't need from the library anymore. And yes, I strongly relied on deepclone and deep merge as I didn't trust my own algos.... I agree with only importing one func instead of the whole library to keep it lightweight.

  • André Brandão
    André BrandãoJun 5, 2021

    Hi Laurie, great article! I think I might have found a typo. Shouldn't the lines that have

    const obj = { a: 1, b: { c: 3, d: 4 } }
    
    Enter fullscreen mode Exit fullscreen mode

    actually be the following?

    const obj = { a: { b: { c: 3, d: 4 } } }
    
    Enter fullscreen mode Exit fullscreen mode
    • Laurie
      LaurieJun 5, 2021

      Ah ya, based on how I access it later that’s correct. I made the examples too quickly.

  • K
    KJun 5, 2021

    To be honest, I maybe used Lodash under 5 times in my dev career, and then just one special function.

  • Valeria
    ValeriaJun 5, 2021

    Speaking of elegant solutions, it's worth checking out ramda. It heavily uses carrying and thus allows to do crazy things with very little overhead (it does the ordinary too, but what's the fun?). Tree-shake friendly, side effects free and doesn't bring bad memories :-)

  • Manuel Beaudru
    Manuel BeaudruJun 5, 2021

    Great article 👍 indeed ECMA specs have greatly improved since 2015 and we don't need to go for third-party as often as before.

    One additional benefit, a major one I think, of using native VS lodash is that your IDE / tooling chain will interpret the code:

    Refactoring a codebase with _get(obj, 'a.b.c') when you change "b" name is going to be difficult, while a?.b?.c can be done automatically by the IDE

  • Xiaoyu Li
    Xiaoyu LiJun 6, 2021

    Any typescript friendly lodash alternative?

    • Laurie
      LaurieJun 7, 2021
    • Ahmad Bilal
      Ahmad BilalOct 1, 2025

      Lodash has been the go-to utility library for over a decade, but it was built for ES5-era JavaScript. I built Highdash as a modern replacement:

      🚀 2–5x faster in many operations

      📦 ~13x smaller bundles (1.9KB gzipped vs 25KB Lodash)

      ✅ TypeScript-first with precise types

      🌲 Perfect tree-shaking, zero dependencies

      Benchmarks, examples, and a migration guide here: GitHub

      I’d love to hear feedback: what Lodash functions do you wish had modern equivalents?

  • Apichart Saekrung
    Apichart SaekrungJun 9, 2021

    +1 I love that Good tools

  • Alex Lohr
    Alex LohrJun 10, 2021

    That's another good point. While some of these helpers are pretty obvious in the functionality (though not in the implementation; you'll end up with a lot of unused edge case handling, take isEmpty for example), many of them require a lot of documentation and are quite difficult to read.

Add comment