I have more nuanced takes on lodash too but I'm putting them in another reply to separate them from the big picture stuff I already mentioned.
Lodash also differs from the standard lib's implementation, notably it's too permissive. Take this example:
const uhoh = null
_.forEach(uhoh, () => {})
uhoh.forEach(() => {})
lodash's forEach has no problem running on a falsey value (it gives you back the value) whereas standard lib leads you to a TypeError.
Two thoughts here. The standard lib forces the programmer to think more about types, which is a good thing. Second is that lodash's more loosey goosey approach acts as vendor lock-in. In two years, when there's 60 lines and 3 files of separation btwn uhoh's assignment and the _.forEach invocation, you won't know whether it's expected to be null or not. So you won't know if you should replace the code with
Lodash also differs from the standard lib's implementation, notably it's too permissive. Take this example:
const uhoh = null
_.forEach(uhoh, () => {})
uhoh.forEach(() => {})
lodash's forEach has no problem running on a falsey value (it gives you back the value) whereas standard lib leads you to a TypeError.
Two thoughts here. The standard lib forces the programmer to think more about types, which is a good thing. Second is that lodash's more loosey goosey approach acts as vendor lock-in. In two years, when there's 60 lines and 3 files of separation btwn uhoh's assignment and the _.forEach invocation, you won't know whether it's expected to be null or not. So you won't know if you should replace the code with
uhoh.forEach(...)
or
(uhoh || []).forEach(...)