DEV Community

[Comment from a deleted post]
Collapse
 
nepeckman profile image
nepeckman

First, lets set some context. Lodash and Underscore come from a time where the JavaScript standard library lacked a lot of typical functions for array manipulation. JavaScript has since added a lot of these functions, and the result can be much more readable than Lodash. When you chain actions in Lodash, it can look a lot like this:

_.map(
    _.filter(
        _.map([1, 2, 3, 4], x => x * x),
        x => x % 2 === 0)
    x => String(x))

This is just difficult to read. To understand the control flow, you have to read these five lines in the order 3, 2, 4, 1, 5. Yeah you could condense some of those lines, but that just results in needing to skip to different places in the same line. Lets compare it with native JavaScript functions:

[1, 2, 3, 4]
    .map(x => x * x)
    .filter(x => x % 2 === 0)
    .map(x => String(x))

Much better. The control flow is obvious and easier to understand. Now it is true that there are some Lodash functions that JavaScript doesn't have natively. If you find yourself needing those functions, I'd recommend a more modern utility library like rambda. Ramdba has the pipe function that can keep the control flow apparent:

R.pipe(
  R.map(x => x * x),
  R.filter(x => x % 2 === 0),
  R.map(x => String(x))
)([1, 2, 3, 4])

This still has some overhead over the native JavaScript, but again, the rambda library contains a lot of functions that JavaScript still lacks.

Collapse
 
kenbellows profile image
Ken Bellows • Edited

Lodash actually has two different ways to do that same thing. Basic lodash has the chain object:

_([1,2,3,4])
    .map(x => x*x)
    .filter(x => x % 2 == 0)
    .map(x => String(x))
    .value()

And then there's the more recent (or modern, if you prefer) lodash/fp module, which looks a lot a like ramda:

fp.pipe(
    fp.map(x => x*x),
    fp.filter(x => x % 2 == 0),
    fp.map(x => String(x))
)([1,2,3,4])

I've heard good things about ramda as well, don't get me wrong, but it's worth knowing all your options fully ☺

And as a side note, I don't know if it makes sense to call ramda "more modern" than lodash; it's been around in some form since late 2013, around a year and a half after lodash came on the scene. IMHO, lodash is one of the most reliable, stable, best maintained projects out there. It's continually improving and being refined, as seen in the fp module. I wouldn't be too quick to dismiss it as outdated just yet

Collapse
 
nepeckman profile image
nepeckman

Yikes, didn't realize lodash already supported all of that! I did a quick search through the documentation, but didn't see that functionality listed 😬 my bad, thanks for setting the record straight!

 
kenbellows profile image
Ken Bellows

Yeah tbh it's slightly hidden in the documentation itself, but the relevant documentation is here. There's a big paragraph there that discusses the difference between _(foo) and _.chain(foo), but the main point is you get an object that lets you chain the usual lodash methods and call .value() when you want the final result.

The basic difference between those two is that _(foo) expects an array or an object, and will automatically drop out of the chain and return the final result value as soon as you call a method that's not guaranteed to return an object or array. So if you call _(foo).map().filter().sortBy(), you'll need .value() at the end, but if you add a .get() or a .reduce(), it will return the value immediately, which can be nice. _.chain(foo) will never drop out of the chain object, you always need to call .value(), which is also helpful sometimes.