在前端开发过程中,为了提高开发效率,我们会经常使用到第三方工具库。
尤其是在一些业务比较复杂的场景,原生 JavaScript 实现可能很啰嗦,但使用第三方工具库,通常一行代码就搞定了。
之前我们介绍过Underscore、Lodash、Ramda 多个第三方库工具库。今天,再给大家分享一个类似但非常独特的库:Lazy.js
简介
Lazy.js是类似Underscore或Lo-Dash的JavaScript工具库,但是它有一个非常独特的特性:惰性求值
。
很多情况下,惰性求值都将带来巨大的性能提升,特别是当处理巨大的数组和连锁使用多个方法的时候。Lazy.js的网站上展示了与Underscore、Lo-Dash比较的图表:
当数组非常大的时候,对于不需要迭代整个数组的方法,例如indexOf和take,Lazy.js的性能提升更为惊人:
安装
Lazy.js没有外部依赖,所以加载Lazy.js非常方便:
<script type="text/javascript" src="lazy.min.js"></script>
如果你希望支持DOM事件序列的惰性求值,那么用这个:
<script type="text/javascript" src="lazy.dom.js"></script>
如果你使用Node.js:
npm install lazy.js
性能对比
让我们创建一个包含1000个整数的数组:
var array = Lazy.range(1000).toArray();
注意我们调用了toArray。如果没有这个,Lazy.range给我们的将不是一个数组而是一个Lazy.Sequence对象,你可以通过each来迭代这个对象。
现在我们打算取每个数字的平方,再加一,最后取出前5个偶数。为了保持代码简短,我们使用这些辅助函数:
function square(x) { return x * x; }
function inc(x) { return x + 1; }
function isEven(x) { return x % 2 === 0; }
我们可以使用Underscore的chain方法实现它:
var result = _.chain(array).map(square).map(inc).filter(isEven).take(5).value();
注意,上面这行语句做了如下事情:
- map(square)迭代了整个数组,创建了一个新的包含1000个元素的数组
- map(inc)迭代了新的数组,创建了另一个新的包含1000个元素的数组
- filter(isEven)迭代了整个数组,创建了一个包含500个元素的新数组
- take(5)这一切只是为了5个元素!
如果你需要考虑性能,你可能不会这么干。因为,它生成了中间数组,且这些中间数组仅仅是为了最后的5个数,后续再无用处。
相反,你会写出类似这样的过程式代码:
var results = [];
for (var i = 0; i < array.length; ++i) {
var value = (array[i] * array[i]) + 1;
if (value % 2 === 0) {
results.push(value);
if (results.length === 5) {
break;
}
}
}
现在我们没有创建任何多余的数组,在一次迭代中完成了一切。貌似很好。但也有问题。
最大的问题在于:这是一次性的代码,我们花了一点时间编写了这段代码,却无法复用。
要是我们能够利用Underscore的表达力,同时得到手写的过程式代码的性能,那该多好啊!
这就是懒惰.js的用武之地!
以下是我们使用 Lazy.js 编写上述代码的方式:
var result = Lazy(array).map(square).map(inc).filter(isEven).take(5);
看上去和用Underscore的代码几乎一样?正是如此:Lazy.js希望带给JavaScript开发者熟悉的体验。每个Underscore的方法应该和Lazy.js有相同的名字和表现,唯一的不同是Lazy.js返回一个序列对象,以及相应的each方法。
重要的是,直到你调用了each才会产生迭代,而且不会创建中间数组。
Lazy.js将所有查询操作组合成一个序列,最终的表现和我们开始写的过程式代码差不多。
但与过程式代码不同的是:Lazy.js确保你的代码是干净的,函数式的。 这样你就可以专注于构建应用,而不是优化遍历数组的代码。
本质上,Lazy.js将所有查询操作组合成一个“序列”,其行为与我们刚才编写的过程代码非常相似。(如果你确实想要一个数组,只需将结果序列出来)
其他
除了性能上优越外,Lazy.js 还有其他特性,诸如生成无穷序列,异步迭代,处理Dom事件(小扩展lazy.dom.js),字符串处理,流处理等功能。
详细的使用,请大家参阅下方链接。
官方地址 https://danieltao.com/lazy.js/ Github地址 https://github.com/dtao/lazy.js/
注意官网首页最后一句话:This library is experimental and still a work in progress. Lazy.js是试验性的,仍在开发中。
因此,在正式环境中,大家酌情使用哦~