为什么Underscore.js的chain()方法不是惰性的?

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相关的问题?
2个回答

12
基本上,要使.chain()按您所描述的那样变成延迟加载,需要几乎有每个方法的两个版本。 您需要立即响应的方法,这些方法执行文档中所说的操作(返回一个数组),并且您需要执行延迟计算的延迟方法(返回期望稍后对每个元素运行的函数)。
一种实现方式是将所有underscore都编写为lazy,并将其作为链接underscore公开。 然后将正常的underscore公开为lazy underscore的包装器,该包装器调用lazy underscore,立即计算,然后返回结果。 主要问题有两个:(1)它需要更多的工作量,(2)它是完全相反的架构,需要将所有underscore都编写为lazy,以支持链式方法的延迟计算。
当然可以做到,就像JSLinq和.NET的LINQ展示的那样,但在开发和维护方面需要付出巨大代价,同时也会增加复杂性和错误的可能性。 在1200行代码中,underscore提供了80个不使用延迟计算的实用程序方法。 JSLinq在7000行代码中提供21种不同实用程序方法的延迟计算。 代码更多,功能数量较低。
存在权衡。 每个开发人员都可以做出自己的决定(只要他们为自己工作)。

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

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

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


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接