2013-07-17 54 views
8

據Underscore.JS源(https://github.com/jashkenas/underscore/blob/master/underscore.js):爲什麼Underscore.js的chain()方法不是懶惰?

// 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(someCollection) 
.map(function1) 
.map(function2) 
.map(function3) 
.value() 

下劃線將創建兩個中間集合,並且將執行三個枚舉。

爲什麼chain()和value()方法沒有像LINQ實現它的方法那樣被執行爲懶惰評估?例如,這條鏈可以被看作:

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

這種實現有沒有JS相關的問題?

回答

12

基本上用你懶惰的方式製作.chain(),它需要每種方法幾乎有兩個版本。您需要立即響應方法來完成文檔中所說的內容(返回一個數組),並且您需要執行懶惰評估的懶惰方法(返回期望稍後爲每個元素運行的函數)。

實現此目的的一種方法是將所有下劃線寫爲惰性,並將其暴露爲鏈式下劃線。然後將普通的下劃線暴露爲一個懶惰的下劃線的包裝,它將調用延遲的下劃線,立即計算並返回結果。有兩個主要問題:(1)需要更多的工作;(2)它是一個完全相反的架構,要求所有下劃線都寫成懶惰,以支持對鏈式方法的懶惰評估。

JSLinq和.NET的LINQ顯然是可行的,但開發和維護的開發時間以及錯誤增加的複雜性和可能性都有巨大的成本。 Underscore提供了1,200行代碼中80種不同實用方法的非懶惰評估。 JSLinq在7,000行代碼中提供了對21種不同實用方法的懶惰評估。更多的代碼,更少的功能。

這是一種折衷。每個開發人員都可以自行做出決定(只要他們爲自己工作)。

7

我相信你正在尋找的東西像Lazy.js

Lazy.js是JavaScript的一個實用工具庫,類似的強調和Lo-短跑,但有一個重要區別:懶惰的評價(也被稱爲延期執行)。在許多情況下,這可以轉化爲卓越的性能,特別是在處理大型數組和/或將多個方法「鏈接」在一起時。對於小型數組上的簡單情況(map,filter等),Lazy的性能應該類似於Underscore或Lo-Dash。

編輯:它看起來就像Lo-Dash may be adding the ability to do lazy evaluation爲好。