본문으로 건너뛰기 Lodash Complete Guide

Lodash Complete Guide

Lodash Complete Guide

이 글의 핵심

Lodash is the most popular JavaScript utility library. It provides functions for arrays, objects, strings, functions, and more — making JavaScript development easier and more consistent.

Introduction

Lodash is a modern JavaScript utility library delivering modularity, performance, and extras. It makes working with arrays, objects, strings, functions, and numbers easier and more consistent.

Why Lodash?

Native JavaScript:

// Deep clone (doesn't work properly)
const clone = JSON.parse(JSON.stringify(obj)); // Loses functions, dates

// Debounce (complex to implement)
let timeout;
function debounce(fn, delay) {
  return function(...args) {
    clearTimeout(timeout);
    timeout = setTimeout(() => fn(...args), delay);
  };
}

With Lodash:

// Deep clone
const clone = _.cloneDeep(obj);

// Debounce
const debouncedFn = _.debounce(fn, delay);

Real-World Adoption

Lodash is the most widely-used JavaScript utility library in the world:

Market Dominance:

  • 140+ million weekly npm downloads (April 2026) - the most downloaded npm package after core Node.js modules
  • 59,000+ GitHub stars - massive community adoption
  • Used in 14+ million public GitHub repositories - more than any other JavaScript utility library
  • Depended on by 95% of top 5,000 npm packages - industry standard

Enterprise Usage:

  • Facebook: Uses Lodash extensively in React codebase and internal tools
  • Google: Employs Lodash in Angular, Google Cloud Console, and Firebase tools
  • Microsoft: Integrated into TypeScript compiler tools and VS Code extensions
  • Netflix: Powers frontend utilities and data transformation pipelines
  • Airbnb: Core part of their JavaScript style guide and codebase

Why Lodash Dominates:

  • Battle-tested: In production since 2012, with billions of downloads
  • Performance: Optimized implementations often faster than native alternatives
  • Consistency: Works the same across all browsers and Node.js versions
  • Deep operations: Handles nested objects/arrays better than native methods
  • Functional programming: Supports FP patterns (curry, compose, pipe)
  • Tree-shakeable: Modern bundlers can eliminate unused functions

Key Statistics:

  • 500+ utility functions covering arrays, objects, strings, numbers, functions
  • 4KB gzipped for common functions (debounce, throttle, cloneDeep)
  • TypeScript support: Full type definitions maintained
  • Zero dependencies: No external packages required

Modern JavaScript vs Lodash:

While ES2015+ added many array methods (map, filter, find), Lodash still excels at:

  • Deep cloning (_.cloneDeep)
  • Debounce/throttle (_.debounce, _.throttle)
  • Deep object operations (_.get, _.set, _.merge)
  • Complex array operations (_.chunk, _.difference, _.groupBy)
  • Functional composition (_.flow, _.curry)

Alternatives:

  • Ramda: Functional programming focus, smaller but different API
  • Underscore: Lodash predecessor, less features
  • Native ES6+: Good for simple operations, but lacks deep utilities

Lodash remains essential in 2026 for production applications requiring robust, tested utilities for complex data transformations.

1. Installation

# npm
npm install lodash

# yarn
yarn add lodash

# CDN (browser)
<script src="https://cdn.jsdelivr.net/npm/lodash@4.17.21/lodash.min.js"></script>

Import Methods

// Import entire library
import _ from 'lodash';

// Import individual functions (recommended for tree-shaking)
import debounce from 'lodash/debounce';
import cloneDeep from 'lodash/cloneDeep';

// CommonJS
const _ = require('lodash');
const debounce = require('lodash/debounce');

2. Array Methods

Map, Filter, Reduce

const users = [
  { id: 1, name: 'Alice', age: 30, active: true },
  { id: 2, name: 'Bob', age: 25, active: false },
  { id: 3, name: 'Charlie', age: 35, active: true },
];

// Map
_.map(users, 'name'); // ['Alice', 'Bob', 'Charlie']
_.map(users, user => user.age * 2); // [60, 50, 70]

// Filter
_.filter(users, { active: true }); // Active users
_.filter(users, user => user.age > 30); // Age > 30

// Find
_.find(users, { name: 'Alice' }); // First match
_.findLast(users, { active: true }); // Last match

// Reduce
_.reduce(users, (sum, user) => sum + user.age, 0); // Total age: 90

Unique, Flatten, Chunk

// Unique
_.uniq([1, 2, 2, 3, 3, 4]); // [1, 2, 3, 4]
_.uniqBy([{ x: 1 }, { x: 2 }, { x: 1 }], 'x'); // [{ x: 1 }, { x: 2 }]

// Flatten
_.flatten([1, [2, [3, [4]]]]); // [1, 2, [3, [4]]]
_.flattenDeep([1, [2, [3, [4]]]]); // [1, 2, 3, 4]

// Chunk (split into groups)
_.chunk([1, 2, 3, 4, 5, 6], 2); // [[1, 2], [3, 4], [5, 6]]
_.chunk(['a', 'b', 'c', 'd'], 3); // [['a', 'b', 'c'], ['d']]

// Compact (remove falsy values)
_.compact([0, 1, false, 2, '', 3, null, undefined]); // [1, 2, 3]

Difference, Intersection, Union

const arr1 = [1, 2, 3];
const arr2 = [2, 3, 4];

// Difference (in arr1 but not arr2)
_.difference(arr1, arr2); // [1]

// Intersection (in both)
_.intersection(arr1, arr2); // [2, 3]

// Union (all unique values)
_.union(arr1, arr2); // [1, 2, 3, 4]

// With objects
const users1 = [{ id: 1 }, { id: 2 }];
const users2 = [{ id: 2 }, { id: 3 }];

_.differenceBy(users1, users2, 'id'); // [{ id: 1 }]
_.intersectionBy(users1, users2, 'id'); // [{ id: 2 }]

Sorting

const users = [
  { name: 'Charlie', age: 35 },
  { name: 'Alice', age: 30 },
  { name: 'Bob', age: 25 },
];

// Sort by single property
_.sortBy(users, 'age');
// [{ name: 'Bob', age: 25 }, { name: 'Alice', age: 30 }, { name: 'Charlie', age: 35 }]

// Sort by multiple properties
_.sortBy(users, ['age', 'name']);

// Sort with custom order
_.orderBy(users, ['age'], ['desc']);
// [{ name: 'Charlie', age: 35 }, ...]

Take, Drop, Sample

const arr = [1, 2, 3, 4, 5];

// Take first n
_.take(arr, 2); // [1, 2]
_.takeRight(arr, 2); // [4, 5]

// Drop first n
_.drop(arr, 2); // [3, 4, 5]
_.dropRight(arr, 2); // [1, 2, 3]

// Random sample
_.sample(arr); // Random element
_.sampleSize(arr, 2); // 2 random elements

// Shuffle
_.shuffle([1, 2, 3, 4, 5]); // Random order

3. Object Methods

Get, Set, Has

const user = {
  name: 'Alice',
  address: {
    city: 'New York',
    zip: '10001',
  },
};

// Get (safe nested access)
_.get(user, 'address.city'); // 'New York'
_.get(user, 'address.country', 'USA'); // 'USA' (default)
_.get(user, 'profile.bio'); // undefined

// Set (create nested path)
_.set(user, 'profile.bio', 'Developer');
// { name: 'Alice', address: {...}, profile: { bio: 'Developer' } }

// Has
_.has(user, 'address.city'); // true
_.has(user, 'address.country'); // false

Pick, Omit

const user = {
  id: 1,
  name: 'Alice',
  email: 'alice@example.com',
  password: 'secret',
  role: 'admin',
};

// Pick (select properties)
_.pick(user, ['id', 'name', 'email']);
// { id: 1, name: 'Alice', email: 'alice@example.com' }

// Omit (exclude properties)
_.omit(user, ['password', 'role']);
// { id: 1, name: 'Alice', email: 'alice@example.com' }

Merge, Assign

const obj1 = { a: 1, b: { x: 1 } };
const obj2 = { b: { y: 2 }, c: 3 };

// Merge (deep)
_.merge(obj1, obj2);
// { a: 1, b: { x: 1, y: 2 }, c: 3 }

// Assign (shallow)
_.assign({}, obj1, obj2);
// { a: 1, b: { y: 2 }, c: 3 }

Keys, Values, Entries

const obj = { a: 1, b: 2, c: 3 };

// Keys
_.keys(obj); // ['a', 'b', 'c']

// Values
_.values(obj); // [1, 2, 3]

// Entries (key-value pairs)
_.toPairs(obj); // [['a', 1], ['b', 2], ['c', 3]]

// From entries
_.fromPairs([['a', 1], ['b', 2]]); // { a: 1, b: 2 }

Clone

const obj = {
  name: 'Alice',
  address: { city: 'NYC' },
  hobbies: ['coding', 'reading'],
};

// Shallow clone
const shallow = _.clone(obj);
shallow.address.city = 'LA'; // Affects original!

// Deep clone
const deep = _.cloneDeep(obj);
deep.address.city = 'LA'; // Doesn't affect original

4. Collection Methods

const users = [
  { name: 'Alice', age: 30, active: true },
  { name: 'Bob', age: 25, active: false },
  { name: 'Charlie', age: 35, active: true },
];

// Group by
_.groupBy(users, 'active');
// {
//   true: [{ name: 'Alice', ... }, { name: 'Charlie', ... }],
//   false: [{ name: 'Bob', ... }]
// }

// Count by
_.countBy(users, 'active'); // { true: 2, false: 1 }

// Key by (index by property)
_.keyBy(users, 'name');
// {
//   Alice: { name: 'Alice', ... },
//   Bob: { name: 'Bob', ... },
//   Charlie: { name: 'Charlie', ... }
// }

// Partition (split by condition)
_.partition(users, { active: true });
// [[active users], [inactive users]]

5. Function Utilities

Debounce

// Debounce (wait until user stops typing)
const search = _.debounce((query) => {
  console.log('Searching for:', query);
}, 300);

// User types: a, ab, abc
// Only searches once after 300ms of no typing

// Cancel pending debounce
search.cancel();

// Execute immediately
search.flush();

Throttle

// Throttle (execute at most once per interval)
const handleScroll = _.throttle(() => {
  console.log('Scrolling');
}, 100);

window.addEventListener('scroll', handleScroll);

// Execute at most once per 100ms

// Cancel
handleScroll.cancel();

Once

// Execute only once
const initialize = _.once(() => {
  console.log('Initialized');
});

initialize(); // Logs: "Initialized"
initialize(); // Does nothing
initialize(); // Does nothing

Memoize

// Cache function results
const fibonacci = _.memoize((n) => {
  if (n <= 1) return n;
  return fibonacci(n - 1) + fibonacci(n - 2);
});

fibonacci(40); // First call: slow
fibonacci(40); // Cached: instant

// Custom cache key
const getUser = _.memoize(
  async (id) => {
    const response = await fetch(`/users/${id}`);
    return response.json();
  },
  (id) => `user-${id}` // Cache key
);

Curry

// Curry (partial application)
const add = (a, b, c) => a + b + c;
const curriedAdd = _.curry(add);

curriedAdd(1)(2)(3); // 6
curriedAdd(1, 2)(3); // 6
curriedAdd(1)(2, 3); // 6

// Useful for reusable functions
const add5 = curriedAdd(5);
add5(10, 15); // 30

6. String Methods

// Case conversion
_.camelCase('hello world'); // 'helloWorld'
_.snakeCase('helloWorld'); // 'hello_world'
_.kebabCase('helloWorld'); // 'hello-world'
_.startCase('hello world'); // 'Hello World'

// Truncate
_.truncate('This is a very long string', { length: 15 });
// 'This is a ve...'

// Pad
_.pad('hi', 8); // '   hi   '
_.padStart('5', 3, '0'); // '005'
_.padEnd('5', 3, '0'); // '500'

// Trim
_.trim('  hello  '); // 'hello'
_.trimStart('  hello  '); // 'hello  '
_.trimEnd('  hello  '); // '  hello'

7. Number Methods

// Random
_.random(1, 10); // Random int between 1 and 10
_.random(1.5, 5.5, true); // Random float

// Clamp (constrain to range)
_.clamp(10, 0, 5); // 5
_.clamp(-5, 0, 10); // 0
_.clamp(3, 0, 10); // 3

// In range
_.inRange(3, 2, 4); // true
_.inRange(5, 8); // true (0 to 8)

8. Real-World Examples

API Request with Debounce

import debounce from 'lodash/debounce';
import axios from 'axios';

const searchAPI = async (query) => {
  const response = await axios.get('/api/search', {
    params: { q: query }
  });
  return response.data;
};

// Debounce to avoid excessive API calls
const debouncedSearch = debounce(searchAPI, 300);

// React example
function SearchInput() {
  const [results, setResults] = useState([]);

  const handleChange = async (e) => {
    const query = e.target.value;
    if (query.length > 2) {
      const data = await debouncedSearch(query);
      setResults(data);
    }
  };

  return <input onChange={handleChange} />;
}

Data Transformation

import { groupBy, mapValues, sortBy } from 'lodash';

const orders = [
  { id: 1, customer: 'Alice', amount: 100, status: 'completed' },
  { id: 2, customer: 'Bob', amount: 50, status: 'pending' },
  { id: 3, customer: 'Alice', amount: 200, status: 'completed' },
];

// Group by customer and sum amounts
const customerTotals = mapValues(
  groupBy(orders, 'customer'),
  (orders) => orders.reduce((sum, order) => sum + order.amount, 0)
);
// { Alice: 300, Bob: 50 }

// Get top customers
const topCustomers = sortBy(
  Object.entries(customerTotals),
  ([_, amount]) => -amount
);
// [['Alice', 300], ['Bob', 50]]

Safe Object Access

import get from 'lodash/get';

// API response
const response = {
  data: {
    user: {
      profile: {
        email: 'alice@example.com'
      }
    }
  }
};

// Safe access (no errors if path doesn't exist)
const email = get(response, 'data.user.profile.email');
const phone = get(response, 'data.user.profile.phone', 'N/A');

// Instead of:
// const email = response?.data?.user?.profile?.email;

9. TypeScript Support

import { debounce, cloneDeep } from 'lodash';

interface User {
  id: number;
  name: string;
}

const users: User[] = [
  { id: 1, name: 'Alice' },
  { id: 2, name: 'Bob' },
];

// Type-safe clone
const cloned: User[] = cloneDeep(users);

// Type-safe debounce
const handleSearch = debounce((query: string) => {
  console.log(query);
}, 300);

10. Bundle Size Optimization

// Bad: imports entire library (~70KB)
import _ from 'lodash';
_.debounce(fn, 300);

// Good: import only what you need
import debounce from 'lodash/debounce';
debounce(fn, 300);

// Even better: use lodash-es for tree-shaking
import { debounce } from 'lodash-es';

11. Performance Tips

1. Chain Operations

// Good: chain for efficiency
_.chain(users)
  .filter({ active: true })
  .sortBy('age')
  .take(10)
  .value();

// Bad: multiple operations
let result = _.filter(users, { active: true });
result = _.sortBy(result, 'age');
result = _.take(result, 10);

2. Reuse Functions

// Good: create once, use many times
const debouncedSearch = _.debounce(search, 300);

// Bad: create new function every time
onClick={() => _.debounce(search, 300)()}

Summary

Lodash simplifies JavaScript development:

  • Array/Object manipulation
  • Function utilities (debounce, throttle, memoize)
  • Deep cloning and safe object access
  • String formatting
  • Cross-browser consistency

Key Takeaways:

  1. Import individual functions to reduce bundle size
  2. Use debounce/throttle for performance
  3. Deep clone with _.cloneDeep
  4. Safe nested access with _.get
  5. Group/transform data with collection methods

Next Steps:

Resources:


Frequently Asked Questions (FAQ)

Q. When would I use this in practice?

A. Complete Lodash guide for JavaScript utilities.

Q. What should I read before this?

A. Follow the previous article or related articles links at the bottom of each post to learn in sequence.

Q. Where can I study this more deeply?

A. Check cppreference and the relevant library’s official documentation. The reference links at the end of the article are also worth using.


Other articles related to this topic.


Keywords Covered in This Article (Related Search Terms)

This article covers Lodash, JavaScript, Utilities, Arrays, Objects, Functions.