是否 possible/recommended 重新使用 lodash 惰性对象?

Is it possible/recommended to re-use lodash lazy objects?

我想知道是否建议传递并重新使用我用 lodash 创建的链式惰性对象。

var filtered = _(nonFiltered).filter(...).map(...);

filtered.each(doStuff).value();

var reMapped = filtered.map(...).object(...);

//keep using reMapped and filtered, sometimes calling .value()

以这种方式使用 lodash 链接对象安全吗?

是的,你绝对可以!

Lodash (>= v3.2) 为您提供了所有您需要的工具。何时执行链由您决定(通过调用 .commit() (见下文)或通过显式或隐式调用 .value() ),您甚至可以通过注入不同的 collections/array/objects/values(通过调用 .plant()(见下文))。

然而,你应该考虑的是:

  1. 性能 --- 每次执行链时都会执行整个链。例如,在您的示例中,如果您执行 reMapped 链,则会再次执行初始 filter()map() 部分。即使您之前执行过 filtered 链。因此在性能方面,在您的代码中的某个点执行链并使用新的 lodash 包装器包装结果可能是有意义的。这就是 commit() 的用途。

    var filtered = _(nonFiltered).filter(...).map(...).commit();
    var reMapped = filtered.(...).commit();
    

    通过这样做,您将执行链并将结果包装在一个新的 lodash 包装器中。当然,这不能很好地与 plant() 一起使用(见下文)。

    Click here for reference on commit()

  2. Variable Lifecycle --- 此外,您需要特别注意,在执行您的链时,您的初始变量 nonFiltered 仍然指向到同一个对象。 IE。你不能创建你的链并期望对 nonFiltered 的新分配自动找到进入链的方式。这就是 plant() 的用途:

    reMapped.plant(nonFiltered).value();
    

    从技术上讲,当调用 plant 时,包装器被克隆,原始包装器保持不变。在性能方面,克隆可以忽略不计。

    Click here for reference on plant()

  3. 内存管理 --- 如果你过于随意地传递包装器,你可能会遇到 nonFiltered 变量(更准确地说object/array 它指向的)通常会被垃圾收集。然而,只要包装器存在,垃圾收集器就无法清理。这可能只会对您的内存占用产生一点影响,但是根据您创建的包装器的数量和存储它们的位置,这也可能意味着您最终可能会显着增加内存占用,具体取决于您最终何时释放包装纸。

    最坏的情况,例如将是,将包装器存储在某种长期存在的对象上(例如存储在 Angular 服务中),包装重量级 $http 响应的结果,可能包含大量不相关的数据,这将减少执行包装器时原始大小的一小部分。

    再次,commitplant 来救援。您可以从两种策略中进行选择:

    1. 要么用一个空值创建你的链(像这样:_().filter(...)...),然后在执行链之前使用 plant(见 (2.))。
    2. 或者只是 commit 链在你定义后立即(见 (1.))