If you're a JavaScript developer in 2016, you're likely at least aware of Lodash, a self-described
modern JavaScript utility library delivering modularity, performance, & extras.
Personally, it's a favorite of mine. From _.compact
all the way to _.toPath
, there's nothing like benefiting from the solution to a problem others have already solved; plus, I find its API to be enjoyable and intuitive.
As human beings, through some combination of habitual use, time constraints, and even laziness, it is possible to become overly reliant on the library. For example, take the function foo
that accepts an array of keys and values to be set upon an object. Calling foo(['greeting', 'hello, world!'])
should return the object { greeting: 'hello, world!' }
.
function foo(keyValueArray) {
const target = {};
while (keyValueArray.length > 0) {
const key = keyValueArray.shift();
const value = keyValueArray.shift();
target[key] = value;
}
return target;
}
While it's true, we could and may want to account for a number of edge cases, like converting foo
's arguments to an Array, or flexibly accepting an object, and so on, let's say we're not going to do that. We demand only an Array be passed to foo, otherwise we're going to throw a custom error InvalidArgument "keyValueArray must be an Array"
.
If we've already required Lodash and want to maintain consistency, we can fall back to Lodash's _.isArray
function.
function foo(keyValueArray) {
if (!_.isArray(keyValueArray)) throw new InvalidArgument('keyValueArray must be an array');
// while...
}
However, is it worth requiring Lodash to check our argument's type if we have yet to do so? Technically, you could require only the function you need, ex: const isArray = require('lodash/fp/isArray')
, but why? Honestly, in my opinion, the answer is consistency, at least that's the only real way I would convince myself to do so. Truthfully, using library utility methods like this is great until it's not. Something like _.isArray
will probably never change its API. The same can't be said for all of Lodash's functions.
It can become a headache ensuring functions work as previously expected between versions and keeping very similar methods straight can become confusing, especially for less experienced programmers, for example: _.filter
, _.findWhere
, _.reject
, _.find
, and _.where
were all a part of Lodash's API at or around the same time. Some did basically the same thing while others deviated slightly.
To avoid this confusion, and limit your exposure to changes in external libraries, consistency in this context should mean consistently deferring to a language's built-in objects and functions.
So, with that said, how can we avoid requiring Lodash with the least amount of complexity? We use a built-in JavaScript method:
function foo(keyValueArray) {
if (!Array.isArray(keyValueArray)) throw new InvalidArgument('keyValueArray must be an array');
// while...
}
In fact, if we look under Lodash's hood, we see in the source that _.isArray
is simply a reference to Array.isArray
, even more encouragement to consistently defer to JavaScript's built-in objects and functions.