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

2019-09-04

JiangRen Mr

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

展开运算符或三个点,接受一个数组数组或通常是可迭代的[... 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

测试结果:

clipboard.png

如上面所看到,在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

 

本文章转载自SegmentFault.

近期开课hot
logo

Follow Us

linkedinfacebooktwitterinstagramweiboyoutubebilibilitiktokxigua

We Accept

/image/layout/pay-paypal.png/image/layout/pay-visa.png/image/layout/pay-master-card.png/image/layout/pay-stripe.png/image/layout/pay-alipay.png

地址

Level 10b, 144 Edward Street, Brisbane CBD(Headquarter)
Level 8, 11 York st, Wynyard, Sydney CBD
Business Hub, 155 Waymouth St, Adelaide SA 5000

Disclaimer

footer-disclaimerfooter-disclaimer

JR Academy acknowledges Traditional Owners of Country throughout Australia and recognises the continuing connection to lands, waters and communities. We pay our respect to Aboriginal and Torres Strait Islander cultures; and to Elders past and present. Aboriginal and Torres Strait Islander peoples should be aware that this website may contain images or names of people who have since passed away.

匠人学院网站上的所有内容,包括课程材料、徽标和匠人学院网站上提供的信息,均受澳大利亚政府知识产权法的保护。严禁未经授权使用、销售、分发、复制或修改。违规行为可能会导致法律诉讼。通过访问我们的网站,您同意尊重我们的知识产权。 JR Academy Pty Ltd 保留所有权利,包括专利、商标和版权。任何侵权行为都将受到法律追究。查看用户协议

© 2017-2024 JR Academy Pty Ltd. All rights reserved.

ABN 26621887572