Skip to content

Lodash - Seq (序列)

Lodash 允许您使用其序列方法(sequence methods)在一个值(如数组或对象)上创建操作链(chains of operations)。这使得复杂的 数据转换(data transformations) 可以采用流畅(fluent)、易读的风格编写。至关重要的是,Lodash 在其显式链式调用(explicit chains)中支持惰性求值(lazy evaluation),这意味着计算会推迟到通过 .value() 请求最终结果时才执行。通过避免创建中间数组或对象,这可以带来显著的性能提升。

要开始一个带有惰性求值的显式链式调用,请使用 _.chain() 包装您的初始值。

方法与语法描述
_.chain(value)创建一个 lodash 包装器(wrapper)实例,启用显式链式调用。允许后续的 Lodash 方法直接在该包装器上调用。
wrapper.value()执行链式序列并返回解析后的值。这会触发推迟(deferred)的计算。
wrapper.plant(value)创建链包装器实例的克隆,其中 value 替换了包装的值。
wrapper.commit()执行链式序列并返回包装后的结果(仍是一个 lodash 包装器)。
_.tap(value, interceptor)调用 interceptor 函数,将 value 作为其参数,并返回 value。在不改变链流程的情况下检查中间结果时很有用。
_.thru(value, interceptor)类似于 _.tap,但 interceptor 的返回值会替换链中的 value。允许将自定义函数集成到链中。

考虑在一个大型数组中查找大于 5 的前两个偶数的平方:

import _ from 'lodash-es';
const numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12];
console.log('--- Eager Evaluation (Native JS / Implicit Lodash Chain) ---');
const eagerResult = numbers
.filter(n => { console.log('Filtering:', n); return n > 5; })
.filter(n => { console.log('Checking even:', n); return n % 2 === 0; })
.map(n => { console.log('Mapping:', n); return n * n; })
.slice(0, 2);
console.log('Eager Result:', eagerResult);
console.log('\n--- Lazy Evaluation (Lodash Explicit Chain) ---');
const lazyResult = _.chain(numbers)
.filter(n => { console.log('Filtering:', n); return n > 5; })
.filter(n => { console.log('Checking even:', n); return n % 2 === 0; })
.map(n => { console.log('Mapping:', n); return n * n; })
.take(2) // More efficient than map().slice() in a lazy chain
.value(); // Execute the chain
console.log('Lazy Result:', lazyResult);

观察控制台输出。在非惰性(eager)版本中,所有数字都被过滤了两次,并且所有产生的偶数都被映射(mapped),然后才进行切片(slicing)。在惰性(lazy)版本中,Lodash 会逐个元素地通过整个链进行处理,直到满足 _.take(2) 的要求。一旦获得所需的两个结果,它就会停止处理,从而避免对数组的其余部分进行不必要的计算。

Lodash 也支持隐式链式调用,当您调用一个 Lodash 函数并传入一个值,并且结果可以传递给另一个 Lodash 函数时,就会发生隐式链式调用。然而,隐式链式调用是非惰性的;每个步骤都会立即执行,类似于原生方法的链式调用。

// Implicit chain (EAGER evaluation)
const implicitResult = _.take(_.map(_.filter(numbers, n => n % 2 === 0), n => n * n), 2);
// This is less readable and performs intermediate array creation.

尽管功能强大,但在现代 JavaScript 中,显式链式调用(_.chain)有时被认为不那么符合习惯,通常更倾向于使用原生方法链式调用或函数组合模式(使用 _.flow 或原生函数组合等工具)来提高可读性。然而,对于大型数据集或复杂序列,惰性求值带来的性能优势仍然是使用 _.chain 的一个重要理由。

当您需要惰性求值以获得性能优势,或者当流畅的链式风格能显著提高复杂、多步转换的可读性时,请使用 Lodash 链式调用。