8

根据 Underscore.JS 来源(https://github.com/jashkenas/underscore/blob/master/underscore.js):

// Start chaining a wrapped Underscore object.
chain: function() {
  this._chain = true;
  return this;
},

// Extracts the result from a wrapped and chained object.
value: function() {
  return this._wrapped;
}

chain() 和 value() 函数只是 Underscore 对象的简单包装器。

因此,如果我使用以下构造:

_.chain(someCollection)
.map(function1)   
.map(function2)
.map(function3)
.value()

Underscore 将创建两个中间集合并执行三个枚举。

为什么 chain() 和 value() 方法没有像 LINQ 实现它的方法那样被实现为惰性求值?例如,这个链可以被视为:

_.chain(someCollection)
.map(function(x){
    return function3(function2(function1(x)));
})
.value();

这种实现有没有与 JS 相关的问题?

4

2 回答 2

12

基本上要.chain()按照您描述的方式变得懒惰,每种方法都需要几乎两个版本。您将需要执行文档所述的即时响应方法(返回一个数组),并且您需要执行惰性求值的惰性方法(返回一个期望稍后为每个元素运行的函数)。

实现这一点的一种方法是将所有下划线编写为惰性并将其公开为链式下划线。然后将普通下划线公开为惰性下划线的包装器,该包装器调用惰性下划线,立即计算,然后返回结果。有两个主要问题:(1)它需要更多的工作,(2)它是一个完全相反的架构,要求所有下划线都写成惰性,以支持链方法的惰性求值。

这当然是可行的,正如 JSLinq 和 .NET 的 LINQ 所展示的那样,但是在开发人员的开发和维护时间以及增加的复杂性和错误的可能性方面存在巨大的成本。Underscore 在 1,200 行代码中提供了对 80 种不同实用方法的非惰性评估。JSLinq 在 7,000 行代码中提供了对 21 种不同实用方法的惰性求值。更多的代码,更少的功能。

有一个权衡。每个开发人员都可以做出自己的决定(只要他们为自己工作)。

于 2013-08-09T02:33:45.350 回答
7

我相信您正在寻找类似Lazy.js的东西:

Lazy.js 是一个用于 JavaScript 的实用程序库,类似于 Underscore 和 Lo-Dash,但有一个重要区别:惰性求值(也称为延迟执行)。在许多情况下,这可以转化为卓越的性能,尤其是在处理大型数组和/或将多个方法“链接”在一起时。对于小型数组上的简单情况(mapfilter等),Lazy 的性能应该类似于 Underscore 或 Lo-Dash。

编辑:看起来Lo-Dash 可能也增加了进行惰性评估的能力

于 2013-08-09T04:52:52.177 回答