前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >这个库让JavaScript变“懒”了,但性能飞升啦

这个库让JavaScript变“懒”了,但性能飞升啦

作者头像
程序员老鱼
发布2023-09-07 08:55:18
2160
发布2023-09-07 08:55:18
举报
文章被收录于专栏:前端实验室

在前端开发过程中,为了提高开发效率,我们会经常使用到第三方工具库。

尤其是在一些业务比较复杂的场景,原生 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非常方便:

代码语言:javascript
复制
<script type="text/javascript" src="lazy.min.js"></script>

如果你希望支持DOM事件序列的惰性求值,那么用这个:

代码语言:javascript
复制
<script type="text/javascript" src="lazy.dom.js"></script>

如果你使用Node.js:

代码语言:javascript
复制
npm install lazy.js

性能对比

让我们创建一个包含1000个整数的数组:

代码语言:javascript
复制
var array = Lazy.range(1000).toArray();

注意我们调用了toArray。如果没有这个,Lazy.range给我们的将不是一个数组而是一个Lazy.Sequence对象,你可以通过each来迭代这个对象。

现在我们打算取每个数字的平方,再加一,最后取出前5个偶数。为了保持代码简短,我们使用这些辅助函数:

代码语言:javascript
复制
function square(x) { return x * x; }
function inc(x) { return x + 1; }
function isEven(x) { return x % 2 === 0; }

我们可以使用Underscore的chain方法实现它:

代码语言:javascript
复制
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个数,后续再无用处。

相反,你会写出类似这样的过程式代码:

代码语言:javascript
复制
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 编写上述代码的方式:

代码语言:javascript
复制
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是试验性的,仍在开发中。

因此,在正式环境中,大家酌情使用哦~

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2023-08-16,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 前端实验室 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 简介
  • 安装
  • 性能对比
  • 其他
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档