When you need to filter, transform, and reduce the same value in sequence, wrapping it once with _(value) reads better than nesting or reassigning a variable at every step. This guide covers when a chain unwraps automatically, when it stays wrapped, and how to inspect a chain mid-sequence. For the complete list of chainable and non-chainable methods, see Chain sequence: the lodash wrapper.
Wrap a value
_(value) returns a lodash wrapper instance. Call any lodash method on it to queue that operation, then call .value() to run the queued operations and get the result.
var users = [
{ user: 'barney', age: 36, active: true },
{ user: 'fred', age: 40, active: false },
{ user: 'pebbles', age: 1, active: true }
];
_(users)
.filter({ active: true })
.sortBy('age')
.map('user')
.value();
// => ['pebbles', 'barney']Implicit chains unwrap automatically
_(value) starts an implicit chain sequence. A method that lodash classifies as non-chainable — one that returns a single value or a primitive, such as head, find, or reduce — ends the sequence immediately and returns the plain result. You do not need to call .value():
_(users)
.filter({ active: true })
.sortBy('age')
.head();
// => { user: 'pebbles', age: 1, active: true }Most lodash methods are chainable and keep you wrapped even when the callback you pass happens to return a primitive. _.thru is one of them:
_([1, 2, 3])
.thru(function (array) { return array.length; })
.value();
// => 3Without the final .value(), that expression is still a wrapper object, not the number 3 — thru is chainable, so lodash does not inspect what your callback returned to decide whether to unwrap.
Explicit chains always require .value()
_.chain(value) starts an explicit chain. Every method call keeps you wrapped, including ones that would auto-unwrap in an implicit chain, so you always finish with .value():
var youngestActive = _.chain(users)
.filter({ active: true })
.sortBy('age')
.head();
typeof youngestActive.value === 'function';
// => true
youngestActive.value();
// => { user: 'pebbles', age: 1, active: true }Use an explicit chain when you want to pass a partially built sequence around before deciding to evaluate it, or when the last method in your sequence happens to be non-chainable and you still want a wrapper back.
Inspect a chain without breaking it
_.tap runs a function for a side effect (such as logging) and returns the original wrapped value unchanged, so it doesn't affect the rest of the chain:
_(users)
.filter({ active: true })
.tap(function (result) { console.log('after filter:', result.length); })
.map('user')
.value();
// => Logs "after filter: 2", then returns ['pebbles', 'barney']Array and string methods on a wrapper
In addition to lodash methods, a wrapper exposes native Array methods (concat, join, pop, push, shift, sort, splice, unshift) and String methods (replace, split) so you can mix them into a sequence:
_([3, 1, 2]).push(9).value();
// => [3, 1, 2, 9]Lazy evaluation
Lodash defers running a chain's queued operations until .value() is implicitly or explicitly called. For array sequences where each step accepts a single-argument iteratee, lodash can also fuse several steps together internally to avoid building intermediate arrays. This is an internal optimization — it does not change the result, only how lodash computes it — so you don't need to design your chains around it.
Next steps
- Look up which methods are chainable by default in Chain sequence: the lodash wrapper.
- Use property paths and partial objects instead of callback functions — see Iteratee shorthands and common patterns.