mrkeyoor.com_
Wed 05 Aug 05:06 UTC
npmUtilsupdated 05 Aug 2026

lodash

Lodash is a grab-bag of utility functions for arrays, objects, strings, and functions: debounce, cloneDeep, groupBy, merge, get, and about 300 more. It sits in your dependency tree as the standard library JavaScript never shipped. It has been on major version 4 since 2016 and, per the OpenJS Foundation announcement in its own README, is now moving to a Feature-Complete maturity stage: stable and maintained, but no new features are coming.

Verdict

Still the safest set of utility implementations ever shipped and fine to keep in existing codebases, but for new projects the language plus es-toolkit covers almost everything at a fraction of the weight. Feature-complete status means this is maintenance mode by design, not neglect.

API stability5/5Major version 4 since 2016 and now formally feature-complete; the API you learned a decade ago still works unchanged.
Docs4/5lodash.com/docs documents every method with examples and is easy to search, but guidance on modern usage (ESM, tree-shaking, when natives suffice) is thin and the FP guide lives off in a wiki.
Maintenance3/5There was a multi-year release gap after 4.17.21, and the project is now funded via the Sovereign Tech Agency in a declared Feature-Complete stage: security and stability fixes yes, new development no. Governance is being rebooted with a new TSC per the README.
Ecosystem5/5166M weekly downloads, per-method mirror packages, lodash-es, babel and webpack plugins, and a decade of Stack Overflow answers; nearly every JS tool understands it.

Use it if

  • You need battle-tested implementations of debounce, throttle, or deep clone and do not want to hand-roll edge cases like leading/trailing calls or circular references
  • You work in a large codebase that already uses it everywhere; consistency beats purity here
  • You need deep object operations natives still do not cover well: merge with nested defaults, groupBy/keyBy, orderBy with multiple keys, isEqual structural comparison
  • You support older runtimes and want utilities that do not assume the newest ECMAScript features
Skip it if

Setup reality

npm install lodash and it just works, no peer dependencies, no config, runs anywhere. The annoyance is bundling: the default package is CommonJS, so bundlers cannot tree-shake it and you must either cherry-pick imports (import debounce from 'lodash/debounce'), switch to lodash-es, or add babel-plugin-lodash. TypeScript types live in a separate @types/lodash install. Teams routinely discover the full library in their bundle months later.

Patterns

Debounce a search inputdebounce-input

import debounce from 'lodash/debounce';

const search = debounce((q) => fetchResults(q), 300);
input.addEventListener('input', (e) => search(e.target.value));
// cancel pending call on teardown
search.cancel();

Create the debounced function once, not inside a render/handler, or every call gets a fresh timer and nothing debounces.

Throttle a scroll handlerthrottle-scroll

import throttle from 'lodash/throttle';

const onScroll = throttle(() => updateHeader(window.scrollY), 100, {
  leading: true,
  trailing: true,
});
window.addEventListener('scroll', onScroll);

Default is leading and trailing both true; set trailing: false if a final late call after the user stops scrolling would be wrong.

Deep clone an objectdeep-clone

import cloneDeep from 'lodash/cloneDeep';

const copy = cloneDeep(original);
copy.settings.theme = 'dark'; // original untouched

Native structuredClone covers most cases now but throws on functions and DOM nodes; cloneDeep copies functions by reference instead of throwing.

Read a nested path with a defaultsafe-get

import get from 'lodash/get';

const city = get(user, 'address.city', 'unknown');
// dynamic paths are where get still earns its keep
const val = get(obj, ['rows', idx, 'cells', col], null);

For static paths use optional chaining (user?.address?.city ?? 'unknown'); get is only worth it when the path is built at runtime.

Group an array of objects by a fieldgroup-by-key

import groupBy from 'lodash/groupBy';

const byStatus = groupBy(orders, 'status');
// { pending: [...], shipped: [...] }
const byYear = groupBy(posts, (p) => p.date.slice(0, 4));

Native Object.groupBy exists in Node 21+ and modern browsers; lodash groupBy is the drop-in for anything older.

Turn an array into a lookup mapindex-by-key

import keyBy from 'lodash/keyBy';

const usersById = keyBy(users, 'id');
const user = usersById[42];

Later duplicates overwrite earlier ones silently; use groupBy if keys can repeat and you need all of them.

Deep merge config with defaultsdeep-merge

import merge from 'lodash/merge';

const config = merge({}, defaults, fileConfig, cliOverrides);

merge mutates its first argument; always pass {} first. Arrays are merged index-by-index, which surprises almost everyone.

Structural equality checkdeep-equal

import isEqual from 'lodash/isEqual';

if (!isEqual(prevFilters, nextFilters)) {
  refetch(nextFilters);
}

Handles nested objects, arrays, dates, and regexes; it is O(n) over the whole structure, so avoid it in hot paths on large objects.

Split an array into batcheschunk-array

import chunk from 'lodash/chunk';

for (const batch of chunk(ids, 100)) {
  await api.bulkFetch(batch);
}

The last chunk is whatever remains and can be shorter than the batch size.

Remove duplicates by a fielddedupe-by-key

import uniqBy from 'lodash/uniqBy';

const unique = uniqBy(contacts, 'email');
const byLower = uniqBy(contacts, (c) => c.email.toLowerCase());

First occurrence wins; sort first if you want the newest record kept.

Whitelist or drop object fieldspick-omit-fields

import pick from 'lodash/pick';
import omit from 'lodash/omit';

const publicUser = pick(user, ['id', 'name', 'avatar']);
const sansToken = omit(session, ['accessToken', 'refreshToken']);

Prefer pick for API responses: an allowlist stays safe when new sensitive fields are added later, omit does not.

Sort by multiple keys with directionmulti-key-sort

import orderBy from 'lodash/orderBy';

const sorted = orderBy(users, ['role', 'createdAt'], ['asc', 'desc']);

Returns a new array (sortBy/orderBy never mutate), and the sort is stable.

Alternatives

PackageRegistryPick it when
es-toolkitnpmNew code that wants the same utility names, smaller and faster, with native ESM and tree-shaking
remedanpmTypeScript-first projects that want data-last pipe-friendly utilities with strong type inference
lodash-esnpmYou want lodash exactly as-is but as ES modules so your bundler can tree-shake it