DEV Community

loading...
Cover image for 5 Must Know Lodash Methods

5 Must Know Lodash Methods

Cameron Lucas
Full-Stack Software Engineer from Denver, CO | FavStack (MongoDB, ExpressJS, ReactJS, NodeJS)
Updated on ・4 min read

Lodash is a Javascript utility library, that helps you work with arrays, objects, strings, and just write fewer functions in general. Let's talk Lodash and some of its most useful methods!

1.) _.get()

The _.get() method can help us find an element in an object. If an element is not found at the specified path we can specify a default value for the _.get() method to return.

const foodObj = {
  favFoods: [
    "Pizza",
    "Chicken Nuggets",
    "Lasagna",
    { favCandy: "Sour Boys Candy" },
  ],
};

// We will use the _.get() method to find my favorite candy.

const myFavCandy = _.get(foodObj, 'favFoods[3].favCandy', 'Chocolate')

// mymyFavCandy => "Sour Boys Candy"
console.log(myFavCandy)
Enter fullscreen mode Exit fullscreen mode

A few things to notice here are

  • The _.get() method can receive three arguments, the first being the object we want to get an element from. The second is the path. The third is the default we want to return if an element was not found.

  • The path to the element is a string.

  • The default retuned value can be any data type (object, string, number, null, etc). By default, the _.get() method will return undefined if an element was unable to be found.

2.) _.find()

You might think that the _find() method is similar to the _.get() method, and yes, they will both return a value we are looking for but, there is a few key differences that are important to understand. Let's first take a look at the _.find() method.

const adoptableDogs = [
  { name: "Rex", age: 7, breed: "German Sheperd" },
  { name: "Sundance", age: 4, breed: "Timber wolf - Mutt" },
  { name: "Milo", age: 0.8, breed: "Husky" },
  { name: "Snowflake", age: 3, breed: "White Lab" },
  { name: "Chip", age: 3, breed: "Pug" },
  { name: "Bolt", age: 5, breed: "White Lab" },
];

// The _.find method will iterates over an object or an array and retun the first element that returns true.
const myNewBestFirend = _.find(
  adoptableDogs,
  // This function will be called on every iteration.
  (obj) => obj.breed === "White Lab" && obj.age > 2,
  2
);

// myNewBestFirend => { name: 'Snowflake', age: 3, breed: 'White Lab' }
console.log(myNewBestFirend);
Enter fullscreen mode Exit fullscreen mode

Kinda cool right? We should talk about those differences though.

  • The _.find() method also takes three arguments, but unlike the _.get() method, the first argument can be an array or an object.

  • The second argument is the function that will fire on every iteration. I used a function in the example above to help solidify this concept. This is important to understand and hopefully helps demonstrate the possibilities.

  • The third argument is the starting index of the collection. Since the _.find() method iterates over every element in a collection. Performance is something to think about with large data sets/collections. You can specify a starting index for the _.find() method to start its search at.

3.) _.map()

The _.map method will iterate over a collection(array, object), and return a new array based on the return value of the function called on each iteration. Let's take a peek.

const adoptableDogs = [
  { name: "Rex", age: 7, breed: "German Sheperd" },
  { name: "Sundance", age: 4, breed: "Timber wolf - Mutt" },
  { name: "Milo", age: 0.8, breed: "Husky" },
  { name: "Snowflake", age: 3, breed: "White Lab" },
  { name: "Chip", age: 3, breed: "Pug" },
  { name: "Bolt", age: 5, breed: "White Lab" },
];

// The _.map method will iterate over the adoptableDogs array and return a new array with all of the dogs' names.
const adoptableDogsNames = _.map(adoptableDogs, (dog) => dog.name);

// adoptableDogsNames => [ 'Rex', 'Sundance', 'Milo', 'Snowflake', 'Chip', 'Bolt' ]
console.log(adoptableDogsNames);
Enter fullscreen mode Exit fullscreen mode

As you can see the _.map() method returns a new array with just the dogs' names as the elements in the array.

4 _.set()

The _.set() method is the opposite of the _.get() method. It will set the value of an element at a specified path. The first argument is the object or array, the second is the path, and the third is the value you desire to set.

const adoptableDogs = [
  { name: "Rex", age: 7, breed: "German Sheperd" },
  { name: "Sundance", age: 4, breed: "Timber wolf - Mutt" },
  { name: "Milo", age: 0.8, breed: "Husky" },
  { name: "Snowflake", age: 3, breed: "White Lab" },
  { name: "Chip", age: 3, breed: "Pug" },
  { name: "Bolt", age: 5, breed: "White Lab" },
];

// Sets the age of the dog at the second index of the adoptableDogs array to 1.
_.set(adoptableDogs, "[2].age", 1);

// adoptableDogs[2] => { name: 'Milo', age: 1, breed: 'Husky' }
console.dir(adoptableDogs[2]);
Enter fullscreen mode Exit fullscreen mode

5.) _.debounce()

This is one of the most powerful lodash methods in my opinion. It can also be very hard to understand what it does and when you might want to use it. The _.debounce() method will return a function. The function returned by the _.debounce() method will delay its invocation until a specified number of milliseconds has elapsed since the last time the function was invoked.

Let's say you were listening to a DOM event (scroll, resize, etc) or API/Webhook route, the event or API may be called multiple times a day or even second. Now let's say you only want to run the function once every 24 hours even if the event or API is called multiple times a second, this is where a debounced function would help. Let's take a peek at the code!

const updateData = _.debounce(
  () => {
    // Code here! We might update some kind of data that might need to be updated once a day.
    console.log("Went and grabbed some new data");
  },
  1000 * 60 * 60 * 24, // 1 Day Timeout
  {
    // defines if the invocation of the function is on the trailing or leading edge of the timeout.
    leading: true,
    trailing: false,
  }
);

// We can call the function returned by the _.debounce method.
updateData();
Enter fullscreen mode Exit fullscreen mode

Conclusion

Lodash is a very helpful utility library, and it has a bunch of helpful methods! We have just barely scraped the surface of lodash in this post. If you would like to know more about the _.debounce method and take a deeper dive into it, check out this blog post by David Corbacho - Debouncing and Throttling Explained Through Examples

You can also follow me on GitHub, Youtube, and Twitter.

Discussion (27)

Collapse
jonrandy profile image
Jon Randy

I'm confused - most, if not all of the examples above can be achieved using less code in plain JS - without the overhead of a library. Using plain JS will also be faster. The debounce one is quite useful, but again - easy to write yourself instead of including a whole library

Collapse
jonrandy profile image
Jon Randy • Edited

1.

const myFavCandy = foodObj ?. favFoods[3] ?. favCandy || 'Chocolate'
Enter fullscreen mode Exit fullscreen mode

2.

const myNewBestFriend = adoptableDogs.find(dog => dog.breed=="White Lab" && dog.age>2)
Enter fullscreen mode Exit fullscreen mode

3.

const adoptableDogsNames = adoptableDogs.map(dog => dog.name)
Enter fullscreen mode Exit fullscreen mode

4.

adoptableDogs[2].age = 1
Enter fullscreen mode Exit fullscreen mode

No 72.5Kb of lodash even remotely required

Collapse
fxbit profile image
Petros Vasileiou

In general for this simple cases yes you don't need lodash, but in more real complex applications is simplify many things especially the chaining.

For example in 1 and 4 when you don't know in compile time the "path", but is something that is user/api/external input how you are going to do it ?

One other thing that I like in lodash is the internal error checking and handling. For example the 2 and 3 example if the adoptableDogs is null/undefined the code is going to get exception, you need to check it before use it.
The lodash is going to return empty array in map and null in find, a consistent result that you don't need to have special check or path in your code flow.

Thread Thread
jonrandy profile image
Jon Randy

I agree. I was merely pointing out that these were poor examples, that do not really give any idea of why, and in what situations Lodash can be beneficial

Collapse
jesterxl profile image
Jesse Warden

Some points:

  1. 4 is doing mutation. In Lodash, set safely gives you a new object (not deep clone, but property copy)
  2. 1 - 4 cannot be curried in normal JavaScript unless you manually wrap them. When you start composing functions, whether using Promise, your own composition, or the new pipeline operator, you end up wrapping all this stuff.
const map_ = func => array => array.map(func)
const find_ = func => array => array.find(func)
["1", "2", "3"]
|> map_(parseInt)
|> find_(isEven)
Enter fullscreen mode Exit fullscreen mode
  1. You can re-use the partially applied functions in 2; creating these yourself just to re-use is tiresome.
  2. Not all JavaScript supports this. Many of us still deal with various IE or old Node.js versions that can't be upgraded yet. #inb4Babel This is why we use Lodash, not just 5 methods that happen to have equivalent features in "the latest JS". We agree with you that if you have that ability in the browser or your current version of Node.js, yes yes, totally use the native functionality.
  3. Outside of AWS Lambda, filesize doesn't matter in Node.js.
Thread Thread
jonrandy profile image
Jon Randy • Edited

So, the writer's example for number 4 then does not even work? The way the example is written implies mutation. This adds even more weight to my contention that these are poor Lodash examples

Thread Thread
jesterxl profile image
Jesse Warden • Edited

No it works, he imported map form lodash, not lodash/fp. Most people when starting to learn will start with Lodash, and that works great for many years. Those who want curry first, data last style coding can use lodash/fp when they are ready (if they want, no pressure). All the same imports, but the parameter order is usually reversed.

Thread Thread
jonrandy profile image
Jon Randy

Ah ok, your comments were referencing a functional version of Lodash

Thread Thread
jesterxl profile image
Jesse Warden

Sort of, it's kind of confusing and frustrating.

Like, Lodash makes it pretty clear some methods mutate the original Array/Object, while others return shallow copies. You'd assume the FP version would, but that's not always the case, so... it's kind of FP, which is better than nothing; at least they document it.

For things like set, though, thankfully, they work the same in both lodash and lodash/fp; it returns a "new"ish Object without mutation.

Thread Thread
jonrandy profile image
Jon Randy

So the writer's example doesn't work

Thread Thread
jesterxl profile image
Jesse Warden

Why you gotta be a troll, man? Guy is just trying to show how cool Lodash is.

Thread Thread
jonrandy profile image
Jon Randy

Not trolling. His examples don't show how good Lodash is, and - as we've established - the fourth example doesn't work if what you said about set not mutating is correct

Collapse
sergio_inge profile image
Sergio Martín

All those "modern JS" native methods did not exist when Lodash was first conceptualized....

Collapse
camskithedev profile image
Cameron Lucas Author • Edited

You are not wrong! Lodash has a bunch of methods that just make doing certain tasks easier. Adding Lodash to your Javascript project adds these methods some other frameworks like Django or Ruby on Rails would have out of the box. Such as the zip method in Ruby on Rails which will zip together two arrays into one. Javascript doesn't have this functionality out of the box... Lodash has a _.zip method. Don't get me wrong you could also do this with the array .map method in Javascript. As for the library overhead you could always import each method individually.

Ex. const zip = require("lodash/zip");

Collapse
miketalbot profile image
Mike Talbot • Edited

You certainly should only import the modules you use, otherwise a few convenience methods are taking up more space than whole frameworks like React. Functions such as debounce() in lodash have tons of options that make them much heavier than lightweight implementations (which are mostly what it is used for) - if you aren't using the options for trailing and leading edges, it's costing "something".

For me in big apps that are likely to use lots of utility methods over time, I'd take Sugar.js because that has some really useful functions - like Date.create("Next monday at 2pm"), debounce etc. It's also 1/3 the size of lodash if you include it all (and you don't have to).

sugar

Collapse
jonrandy profile image
Jon Randy

Probably would have been better to show examples of where using Lodash would actually have some benefit

Thread Thread
camskithedev profile image
Cameron Lucas Author

Maybe in my next post! 😉 say tuned lol!

Thread Thread
jonrandy profile image
Jon Randy • Edited

'Tuned'

Thread Thread
murkrage profile image
Mike Ekkel

I see what you did there 👀

Collapse
bukazoltan profile image
bukazoltan

I don't know anything about ruby on rails but isn't that concat? w3schools.com/jsref/jsref_concat_a...

Thread Thread
camskithedev profile image
Cameron Lucas Author

It's a little different concat would join the two arrays. So if you had [1, 3, 5] and [2, 4]. The results of concatenation would be [1, 3, 5, 2, 4]. The zip method would zip the two arrays together like a zipper. The results would look like this [1, 2, 3, 4, 5]

Thread Thread
bukazoltan profile image
bukazoltan

So basically concat + sort?

Collapse
leob profile image
leob

I think you have a point especially on the client - downloading dozens of extra KB's is not a good idea unless it's really necessary ... server side (node.js) this is less of an issue.

Collapse
sebbdk profile image
Sebastian Vargr • Edited

Recommendation: Do not use Lodash in current year.

Like others here have pointed out, It is a literal waste of kb's in your payload. :)

Collapse
doooby profile image
Ondřej Želazko • Edited

well, import { debounce } from 'lodash'; kinda takes your argument away (there are even separate packages for everything). also, in past years I'd been writing my own debounce function in every project, it isn't that a complex mechanism. I'm not that foolish any more. the lodash's version is superior and documented. and that's gist of it.

Collapse
sebbdk profile image
Sebastian Vargr

debouncing is not Lodash tho, it’s part of the library by practical coincidence.

It could also be a separate package like you point out.

Lodash was made in an age when array methods where lacking and polyfiling was less common.

If they changed the focus of the library, then I did not get the memo. :)

Collapse
tanth1993 profile image
tanth1993

in Lodash, I use debounce and cloneDeep most :)