JS中如何提高展开运算符的性能

79次阅读

共计 2546 个字符,预计需要花费 7 分钟才能阅读完成。

作者:Dmitri Pavlutin
译者:前端小智
来源:dmitripavlutin.

为了保证的可读性,本文采用意译而非直译。

想阅读更多优质文章请猛戳 GitHub 博客, 一年百来篇优质文章等着你!

为了回馈读者,《大迁世界》不定期举行(每个月一到三次),现金抽奖活动,保底 200,外加用户赞赏,希望你能成为大迁世界的小锦鲤,快来试试吧

本文主要讲解怎么提高展开运算的性能,在此之前先简单说说展开运算在数组中的工作原理。

展开运算符或三个点,接受一个数组数组或通常是可迭代的 [... arrayOrIterable] 并将数组元素分解,并使用这些分解部分构造一个新数组。

展开运算符可以放在数组中的任何位置:

const numbers = [1, 2, 3];
[0, ...numbers];    // => [0, 1, 2, 3]
[0, ...numbers, 4]; // => [0, 1, 2, 3, 4]
[...numbers, 4];    // => [1, 2, 3, 4]

现在有一个有趣的问题,展开运算符在数组中的位置是否可以提高性能? 让咱们来 look look。

1. 附加到头部和尾部函数

在开始对比性能之前,先定义两个函数。

第一个函数:appendToTail()

function appendToTail(item, array) {return [...array, item];
}

const numbers = [1, 2, 3];
appendToTail(10, numbers); // => [1, 2, 3, 10]

appendToTail()函数功能主要是将 item插入数组的末尾。

第二个函数 appendToHead()

function appendToHead(item, array) {return [item, ...array];
}

const numbers = [1, 2, 3];
appendToHead(10, numbers); // => [10, 1, 2, 3]

appendToHead() 是一个纯函数,它返回一个新数组,通过 [item,... array] 骚操作将 item 放到所传入数组的后面。

乍一看,没有理由认为这些函数的性能会不同,但是,事实胜于熊辩,来 look look.

2. 性能测试

在 MacBook Pro 笔记本电脑上用以下 3 个浏览器的运行[... array,item][item,... array],来看看对应的性能:

  • Chrome 76
  • Firefox 68
  • Safari 12.1

测试结果:

如上面所看到,在 FirefoxSafari浏览器中 [... array,item][item,... array]的性能基本一样。

但是,在 Chrome 中,[... array,item]的执行速度比 [item,... array] 快两倍。这个结果对咱们来说很有用。

要在 Chrome 中提高展开运算符的性能,只需要将展开操作放到数组的开头就哦了。

const result = [...array, item];

但这又是为啥,为什么会发生这种情况?

3. 快速路径优化(fast-path optimization)

启动 V8 引擎的 7.2 版本(为 Chrome 中的 JS 执行提供支持),可以对展开运算符进行新的优化:快速路径优化

简单说,它的工作原理如下:

如果没有这种优化,当引擎遇到一个展开操作符 [...iterable, item],它调用iterable 对象的 iterator (iterator.next())方法。在每次迭代中,最后返回的数组的内存都会增加,并将迭代结果添加到其中。

但是快速路径优化检测到一个已知的可迭代对象 (就像一个整数数组),并完全跳过iterator 对象的创建。然后,引擎读取扩展数组的长度,只为结果数组分配一次内存。然后传递展开数组的索引,将每个元素添加到结果数组中。

快速路径优化会跳过迭代对象的创建,只为结果分配一次内存,从而性能提高。

4. 支持数据结构

快速路径优化适用于以下标准 JS 数据结构。

array

const numbers = [1, 2, 3, 4];

[...numbers, 5]; // => [1, 2, 3, 4, 5]

string

const message = 'Hi';

[...message, '!']; // => ['H', 'i', '!']

set

const colors = new Set(['blue', 'white']);

[...colors, 'green'];          // => ['blue', 'white', 'green']
[...colors.values(), 'green']; // => ['blue', 'white', 'green']
[...colors.keys(), 'green'];   // => ['blue', 'white', 'green']

map

关于 map,只支持map.keys()map.values()方法

const names = new Map([[5, 'five'], [7, 'seven']]);

[...names.values(), 'ten']; // => ['five', 'seven', 'ten']
[...names.keys(), 10];      // => [5, 7, 10]

总结

当展开数组位于数组文本的开头时,咱们可以通过 快速路径优化 获得性能提升。该优化在 V8 引擎 v7.2 中可用(在 Chrome v72 和 NodeJS v12 中提供)。

通过 快速路径优化 [... array,item] 的执行速度至少比 [item,... array] 快两倍。

请注意,虽然 f 快速路径优化确实很有用,但是在大多数情况下,可以不用强制进行优化,因为最终用户很可能不会感觉到差别,当然,如果咱们在处理大型数组,就可能些优化方案。

代码部署后可能存在的 BUG 没法实时知道,事后为了解决这些 BUG,花了大量的时间进行 log 调试,这边顺便给大家推荐一个好用的 BUG 监控工具 Fundebug。

原文:https://dmitripavlutin.com/ja…

交流

干货系列文章汇总如下,觉得不错点个 Star,欢迎 加群 互相学习。

https://github.com/qq44924588…

我是小智,公众号「大迁世界」作者,对前端技术保持学习爱好者。我会经常分享自己所学所看的干货,在进阶的路上,共勉!

关注公众号,后台回复 福利,即可看到福利,你懂的。

正文完
 0