The most common reaction to Just is why not just use Lodash? Lodash is brilliantly engineered, well maintained and battle tested and there are many reasons to use it. Here I'll try to document (as impartially as possible) the cases where you might want to use Just instead.
- Use Lodash if it covers an edge case you care about (Lodash is very good at covering edge cases)
- Use Lodash if your app is going to be processing vast datastructures (100,000+ records) and the runtime performance gains exceed the extra page load lag from the increased JavaScript payload.
- Use Lodash, Underscore or Ramda if they provide a method that Just doesn't (and there are many).
- Use Just if you care about JavaScript footprint (and none of the above applies).
Alex Russell puts it better than I could:
We regularly see sites loading more than 500KB of script (compressed). This matters because all script loading delays the metric we value most: Time to Interactive. Sites with this much script are simply inaccessible to a broad swath of the world’s users; statistically, users do not (and will not) wait for these experiences to load. Those that do experience horrendous jank.
JavaScript size is especially critical for mobile web development. As Alex points out, 45% of mobile connections occur over 2G worldwide. 75% of connections occur on either 2G or 3G.
Just utils nearly all weigh in at a tiny fraction of the size of their Lodash counterparts. They're hand written so they include only essential code. All of them are well under 1kB minfied/gzipped¹.
Assuming you don't want to import the entire Lodash monolith, there are two ways to access individual Lodash modules. You can load submodules directly from the Lodash mono-library:
import camelCase from 'lodash/camelcase'
Alternatively, Lodash Modularized provides a set of dependency-free modules:
import camelCase from 'lodash.camelcase'
Lodash Modularized modules are really modular by name only. They're still dependant on other Lodash functions, the only difference is those dependencies are now inlined within the module. The upshot is Lodash modules share a lot of redundant code and are generally much bigger than they need to be.
Module for module, both Lodash import techniques yield the same size, but if you want to import several Lodash modules the earlier technique becomes more efficient, since common dependencies are ony loaded once.
Check out the Just vs Lodash file size comparisons below. (Please note the disclaimer in the footnote¹)
The following Just utils pass all Lodash unit tests for core functionality. The only "fails" are by design, for opinionated behaviors (notably argument coercion) which Just intentionally avoids. These are noted in the table.
Just (size¹) | Lodash (Size¹) | Differences with Lodash |
---|---|---|
just-values (127b) | values (562b) | a |
just-omit (80b) | omit (2540b) | a, l |
just-pick (75b) | pick (874b) | a, l |
just-map-values (54b) | mapvalues (4470b) | a, b, j, k |
just-map-keys (57b) | mapKeys (4470b) | a, b, j, k |
just-safe-get (65b) | get (1750b) | i |
just-safe-set (108b) | set (1930b) | i |
just-split (145b) | chunk (756b) | a, b |
just-flatten-it (99b) | flattendeep (549b) | a |
just-tail (48b) | tail (111b) | a |
just-unique (268b) | uniq (1650b) | a |
just-zip-it (173b) | zip (517b) | a, c |
just-compact (84b) | compact (53b) | a |
just-intersect (115b) | intersection (361b) | a, n, o |
just-camel-case (180b) | camelCase (2020b) | a |
just-kebab-case (149b) | kebabCase (1720b) | a |
just-snake-case (149b) | snakeCase (1720b) | a |
just-left-pad (316b) | padstart (1190b) | a, m |
just-right-pad (316b) | padEnd (1190b) | a, m |
just-clamp (116b) | clamp (355b) | a, g, h |
just-range (137b) | range (705b) | (none) |
just-curry (72b) | curry (2860b) | a, d, e |
just-partial-it (98b) | partial (2940b) | a, f |
just-once (78b) | once (465b) | a |
a. Just expects correct argument type, Lodash coerces arguments to expected type
b. Just does not invoke other Lodash utils as part of its implementation
c. Lodash zip returns []
if no arguments, Just requires at least one argument
d. Lodash curry supports _
placeholders. Just expects only just-partial to support such placeholders.
e. Lodash curry can be used as a constructor
f. instances of Lodash partial have a unique instanceof
value.
g. Lodash clamp works without a lower bound arg. Just always requires lower and upper bounds.
h. If either bound is NaN
, Lodash returns 0
, Just returns NaN
.
i. just-get and just-set follows dotty for (obj, ['a.b'])
style arguments. Lodash uses its own rules.
j. Lodash invokes _.identity
when predicate function is nullish
k. Lodash accepts _.property
shorthand instead of predicate function.
l. Lodash will flatten arguments to pick and omit. e.g. pick(obj, ['a', 'b'], 'c')
becomes pick(obj, 'a', 'b', 'c')
m. When splitting left and right multi-character pads, Lodash truncates from the outside:
padStart('cde', 4, 'ab')
yields 'acde'
Just truncates from the inside:
just-left-pad('cde', 4, 'ab')
yields 'bcde'
n. Lodash works with just one argument, Just expects two
o. Lodash treats NaN
values as equal to one other
In addition, these Just utilities, while lacking the additional features of their Lodash equivalents (noted below), match the feature set / behavior of underscore and other comparable libraries.
Just (size¹) | Lodash (size¹) | Extra Lodash features |
---|---|---|
just-truncate (54b) | truncate (1510b) | a |
just-debounce (90b) | debounce (797b) | b, c, d |
just-throttle (76b) | throttle (857b) | b, c, d |
just-merge (142b) | merge (4220b) | e, f, g |
just-clone (157b) | clonedeep (3360b) | e, f, g |
a. In addition to a suffix arg, Lodash truncate accepts a separator expression, which when present is used as the truncation point.
b. Lodash has a leading and trailing option, Just only has a leading option.
c. Lodash cancels delayed calls.
d. Lodash has a flushed
method that can be applied to throttles/debounces.
e. Lodash can merge circular references.
f. Just only merges plain objects, regular arrays, functions and primitives. Lodash merges additional non-plain object types.
g. Lodash treats sparse arrays as dense.
See the original blog post