Lazy.js 类Underscore的JavaScript工具库,利用Nodejs实现惰性求值带来高性能
Lazy.js 类Underscore的JavaScript工具库,利用Nodejs实现惰性求值带来高性能
Lazy.js是类似Underscore或Lo-Dash的JavaScript工具库,但是它有一个非常独特的特性:惰性求值。很多情况下,惰性求值都将带来巨大的性能提升,特别是当处理巨大的数组和连锁使用多个方法的时候。
Lazy.js的网站上展示了与Underscore、Lo-Dash比较的图表:
当数组非常大的时候,对于不需要迭代整个数组的方法,例如indexOf和take,Lazy.js的性能提升更为惊人:
惰性求值的威力
假设我们对包含1000个整数的数组进行一些操作
Underscore 版本,会生成许多巨大的中间数组:
var result = _.chain(array).map(square).map(inc).filter(isEven).take(5).value();
Lazy.js 版本,不会生成中间数组。
var result = Lazy(array).map(square).map(inc).filter(isEven).take(5);
Lazy.js的函数和 Underscore 几乎一模一样,只不过它返回的不是数组,而是带each 方法的序列对象。
它不会生成中间数组,而且只有在调用each
方法的时候才产生迭代!
同理,进行字符串处理(惰性地):
var firstFiveLines = Lazy(text).split("\n").take(5);
text
很大的时候也没关系,不会生成巨大的数组。
它还能生成无穷数列,把DOM事件封装成序列,等等,等等。
更多请看 GitHub上的 README.md。
我把README.md 翻成了中文:
摘要
本文介绍了Lazy.js,一个类似于Underscore或Lo-Dash的JavaScript工具库,但具有惰性求值的独特特性。惰性求值可以显著提高性能,特别是在处理大型数据集时。通过示例代码,我们将展示Lazy.js如何避免生成不必要的中间数组,并仅在需要时才执行计算。
惰性求值的威力
示例:处理大型整数数组
假设我们有一个包含1000个整数的数组,我们想要对其进行一系列操作,如平方、加1、过滤偶数并取前5个结果。
Underscore 版本
var array = Array.from({length: 1000}, (_, i) => i);
var result = _.chain(array)
.map(x => x * x) // 平方
.map(x => x + 1) // 加1
.filter(x => x % 2 === 0) // 过滤偶数
.take(5) // 取前5个
.value(); // 执行所有操作
在这个例子中,Underscore会生成多个中间数组,这可能会导致内存占用增加和性能下降。
Lazy.js 版本
var Lazy = require('lazy.js');
var array = Array.from({length: 1000}, (_, i) => i);
var result = Lazy(array)
.map(x => x * x) // 平方
.map(x => x + 1) // 加1
.filter(x => x % 2 === 0) // 过滤偶数
.take(5); // 取前5个
在Lazy.js版本中,操作只是构建了一个执行链,而不会立即生成中间数组。只有在调用result.toArray()
或result.each(...)
等方法时,实际的计算才会被执行。
示例:处理大型文本
如果我们要从一个非常大的文本文件中提取前5行,Lazy.js同样可以提供更好的性能:
var text = `...`; // 假设这是一个非常大的文本
var firstFiveLines = Lazy(text.split("\n"))
.take(5)
.toArray(); // 将结果转换为数组
在这个例子中,Lazy.js不会一次性生成包含所有行的数组,而是逐步读取并处理文本。
总结
Lazy.js通过惰性求值的方式,显著提高了处理大型数据集时的性能。通过避免生成不必要的中间数组,Lazy.js使得数据处理更加高效。更多关于Lazy.js的详细信息可以在其GitHub仓库中找到,包括详细的API文档和示例代码。
不太看好~ 尤其是 ES6 的 generators
和 iterators
普及之后!
目前来说 lodash 足矣。
在用lodash
mark
Lazy.js 是一个类似于 Underscore 或 Lo-Dash 的 JavaScript 工具库,它特别之处在于支持惰性求值(lazy evaluation),这在处理大型数据集时能显著提高性能。惰性求值意味着直到必要时才执行计算,从而避免了不必要的中间结果生成。
示例代码
假设我们有一个包含 1000 个整数的数组,并需要对其进行一系列操作:
const Lazy = require('lazy.js');
// 使用 Underscore 进行处理
const array = Array.from({ length: 1000 }, (_, i) => i);
const underscoreResult = _.chain(array)
.map(x => x * x) // 平方
.map(x => x + 1) // 加1
.filter(x => x % 2 === 0) // 只保留偶数
.take(5) // 取前五个元素
.value();
console.log(underscoreResult); // 打印结果
// 使用 Lazy.js 进行处理
const lazyResult = Lazy(array)
.map(x => x * x)
.map(x => x + 1)
.filter(x => x % 2 === 0)
.take(5)
.toArray(); // 转换为数组
console.log(lazyResult); // 打印结果
解释
-
Underscore:
_.chain(array)
开始一个链式操作。.map(...)
和.filter(...)
会立即生成中间数组。.take(5).value()
执行最终的取值操作。
-
Lazy.js:
Lazy(array)
创建一个惰性序列。.map(...)
和.filter(...)
不会立即执行,而是延迟到.toArray()
被调用时。.toArray()
强制执行所有操作并返回最终结果。
由于 Lazy.js 的惰性求值特性,它避免了生成大量的中间数组,从而在处理大数据集时更加高效。