DEV Community

Lodash and Underscore, is there still a case?

Adam Crockett 🌀 on September 05, 2019

I used to say that JavaScript is mature enough to not need polyfiling by the likes of Lodash or Underscore. This opinion is in the same vein as jQu...
Collapse
 
ahferroin7 profile image
Austin S. Hemmelgarn • Edited

I se two big advantages to Lodash/Underscore other than providing slightly stricter FP semantics:

  • They make your code more concise, usually in a good way. ECMA and W3C seem to love long super descriptive names for functions. Using Lodash or Underscore lets you avoid such needless verbosity without compromising on readability. _.has(x, y) is a whole lot easier to read than x.hasOwnProperty(y), especially if you're not using syntax hilighting, but doesn't reduce the amount of relevant information being conveyed to anyone reading the code. This is also, coincidentally, one of the arguments for continuing to use jQuery ($('foo') is a whole lot more concise than document.querySelector('foo')).
  • It helps you avoid having to write boilerplate code. Yeah, you could write your own symmetric difference algorithm for arrays, but it's a whole lot easier to just use _.xor(x, y) and worry about coding the actual application, especially when you've got a deadline approaching. The less generic code you have to write, the more time you can focus on actually getting the application itself written.

I honestly feel both points are far stronger arguments than making FP in JS nicer, especially considering the fact that most of making FP nicer in JS at this point is just enforcing FP patterns (the language itself is already very FP friendly).

Collapse
 
adam_cyclones profile image
Adam Crockett 🌀

Your first point reminds me of the awquard case of the JavaScript Map, although vastly superior with an API just like you describe, nobody seems to use them despite the ease of use and performance improvement.

I don't really disagree with anything you say. Thanks for chipping in.

Collapse
 
ahferroin7 profile image
Austin S. Hemmelgarn

nobody seems to use them despite the ease of use and performance improvement.

There are a lot of sites that transpile down to earlier versions of ECMAScript revisions. In such a case, there's no performance benefit to using new features, and quite often they actually make performance worse. I suspect that's a large part of it, and we'll probably see usage of some of these features pick up more as Internet Explorer and Opera Mini finally die off.

Thread Thread
 
adam_cyclones profile image
Adam Crockett 🌀

That's fair. I do wish that the web would move a little faster in some areas. Browsers being one of them. And an approximation of a thing is not a real thing. I gues I'm just talking in an ideal world scenario.

Thread Thread
 
ahferroin7 profile image
Austin S. Hemmelgarn

I mean, Opera Mini really is dead already for most purposes if you aren't dealing with some really big site. IE is still hanging on, but mostly corporate usage and not 'normal' users.

It's well within reason to just refuse to support either if you're doing something small. The issue is that people don't choose to do that, or they just kind of decide to use Babel without thinking (and thus make the site slow for all their actual users who aren't using browsers that need old JS).

Collapse
 
amyblankenship profile image
AmyBlankenship • Edited

I don't see anyone talking about what to me is the biggest advantage of lodash--the various syntaxes you can use for iteratees. So, _.map(myObj, 'someProp.innerArray[0]'), or _.find(someArray, {color: 'green'}) just completely blows the hell out of anything you could write yourself in the 10 seconds it took me to write that. And then there's the fact that the Collection methods let you treat arrays and objects as basically the same.

Also, studying the lodash docs really gives you a feel for what's possible in functional programming and some ways you might want to use it to solve your own problems. I think really understanding the lodash docs made me a much better programmer. I'd highly recommend this for people who don't already automatically reach for FP on a regular basis.

To me the downside is the cyclomatic complexity is unknown for all the functions. So you have no idea what the performance impact is of deciding to use a lodash function, whereas you do know for your own.

Collapse
 
adam_cyclones profile image
Adam Crockett 🌀

The first part of what you mentioned, I'm not convinced that this is not already covered by popular es6 array methods unless I am missing something?

Collapse
 
amyblankenship profile image
AmyBlankenship • Edited

Can you provide an example of syntax where you'd provide a string with the path to a deeply nested object property to use in ES6 map or where you'd be able to provide an object that describes a property and value to filter on? If such exists, I have never seen it described anywhere. AFAIK those methods always take a function.

Thread Thread
 
adam_cyclones profile image
Adam Crockett 🌀

I don't think one method does exist off the top of my head. Can you give me a data structure snippet to visualize.

I guess you might want to use entries and perhaps flat, not working on nested data but flat copies, that's got to be more efficient.. maybe. IDK but I agree that convince sounds like the winner here. Anyway I always check this sort of opinion, it's interesting. 😁

Thread Thread
 
amyblankenship profile image
AmyBlankenship • Edited

So, if your data structure is

[{firstName: 'John', lastName: 'Smith', offspring: [{name:'Katie', gender: 'F'}, {name: 'Mark', gender: 'M'}],
{firstName: 'Jill', lastName: 'Jones', offSpring: [{name: 'Doug', gender: 'M'}]}]

and you're looking for someone whose firstborn is a son (in case of pestilence), you can do _.find(users, ['offspring[0].gender', 'M'])

Or if you want the last name of the second user, you can do _.get(users, '[1].lastName')

Or if you want to find all users with offspring
_.filter(users, 'offspring.length')

I just don't see easily being able to do that with native ES6 functions out of the box.

Thread Thread
 
adam_cyclones profile image
Adam Crockett 🌀 • Edited
const arr = [{
    firstName: 'John',
    lastName: 'Smith',
    offspring: [{
        name:'Katie', 
        gender: 'F'
    }, {
        name: 'Mark',
        gender: 'M'
    }],
    {
        firstName: 'Jill', 
        lastName: 'Jones', 
        offSpring: [{
            name: 'Doug', 
            gender: 'M'
        }]
    }
];

arr.find(person => person.offspring.find ... // Point taken this is a bit more wordy😁
Thread Thread
 
amyblankenship profile image
AmyBlankenship

So in other words, you can't do it out of the box with ES6 functions--you have to write additional functionality yourself (which your team is then responsible for testing and maintaining).

Collapse
 
gsto profile image
Glenn Stovall

I still find the odd use case. It's handy now that you can import individual functions so you aren't adding bloat to your bunder. Here's what a quick grep tells me is in my current project:

  • throttle
  • inrange
  • flatten
  • isempty
  • omit

As far as functional and class patterns go, here's my take: JavaScript is not a functional language. JavaScript is not an object-oriented language. JavaScript is its own weird thing. Trying to make JavaScript do a Haskell or C# impersonation is only going to leave you with code that more complex and harder to maintain than it needs to me.

Collapse
 
johnkazer profile image
John Kazer • Edited

If you make JS more fully functional, there would be little point in using it - just switch to Elm or ClojureScript (which compile to JS). Part of the reason for sticking with JS with a functional style now is that it offers more flexibility than Elm or ClojureScript. Writing your own functions or updating a library is much easier than issuing new versions of JS!

Collapse
 
ssimontis profile image
Scott Simontis

I would love to, but I have always worked in places which were entirely distrustful of technologies unless "everyone else was doing it." They asked for ideas to be innovative, but saw anything unknown or new as a risk. I could get away with using Lodash, so I did what I could without getting fired.

I don't know I would feel comfortable using Elm in a Production app yet. It's getting there and I love the language, but it's not quite there yet. I have been meaning to pick up Clojurescript. Tried Purescript and the outdated documentation was frustrating, plus the toolset was not desirable. I love ReasonML, but getting it to compile into Javascript seems like some arcane art. The deployment process, or what little I could find describing it, was a pain in the butt and Bucklescript was, at the time, holding the entire product back because it didn't work very well and was out of date.

Collapse
 
adam_cyclones profile image
Adam Crockett 🌀

Who said anything about issuing new versions of a language? I just said wouldn't it be nice is all 😀

Collapse
 
adam_cyclones profile image
Adam Crockett 🌀

Thanks for taking the time to look this up, it's really interesting. But I guess not needing to import everything is grounds for me to say, okay I might take these libraries more seriously. Rolling my own is fun but not over and over and over because I forgot where I keep them. My codepen is vast!

Collapse
 
lfjsa profile image
Ludwig Antilli

No love for Ramda? Its data-last approach and auto curried functions make composition a charm.

Would choose it over the other two any day.

Collapse
 
adam_cyclones profile image
Adam Crockett 🌀

Less no love no more no clue 😂

Collapse
 
mdhilwan profile image
mdhilwan

What I usually do, is I will replicate just the functions that I need instead of installing lodash / underscore. Because what I realised is that I only depend on less than 4-5 of their methods.

Collapse
 
adam_cyclones profile image
Adam Crockett 🌀

This seems to be the case for a couple of the lovely Devs above. I think if you have the time to kill then go for it. 😁