您应该停止做的3个JavaScript性能错误

如果我告诉您您所知道的一切都是谎言,那怎么办?如果您了解我们心爱的ECMAScript近年来发布的一些关键功能,那实际上会是危险的性能陷阱,看起来像是在光滑的一行回调函数代码中涂上糖?
这个故事开始于几年前,追溯到ES5的幼稚时代。

您应该停止做的3个JavaScript性能错误

我仍然清楚地记得这一天,ES5发行了,伟大的新数组函数被引入到我们亲爱的JavaScript中。 其中包括forEach,reduce,map,filter –它们使我们感到语言在不断发展,变得越来越功能化,编写代码变得更加有趣和流畅,并且结果更易于阅读和理解。

大约在同一时间,出现了一个新环境-Node.js,它使我们能够从前端到后端进行平滑过渡,同时真正地重新定义了完整的堆栈开发。

如今,使用V8上最新的ECMAScript的Node.js试图被视为主要的联盟服务器端开发语言的一部分,因此,它需要证明其性能值得。 是的,要考虑的参数太多了,是的,没有任何一种比所有语言都优越的了。 但是,使用上面提到的数组函数提供的现成功能编写JavaScript是否有助于或损害您的应用程序性能?

此外,随着最终用户计算机的不断壮大和网络速度的提高,客户端javascript不仅是演示文稿/视图的解决方案,它还被认为是一种合理的解决方案,但是当我们的应用程序需要快速的性能并且可能是一个出色的应用时,我们可以依靠它吗?非常大而复杂?

为了测试这些问题,我尝试比较了几种情况,并深入了解了我得到的结果。 我在macOS上的Node.js v10.11.0和Chrome浏览器中执行了以下测试。

1.遍历数组

我想到的第一种情况是对一万个项目进行求和,这是我偶然发现的有效解决方案,它试图从数据库中获取一个长项目表并使用总和对其进行增强,而没有额外的费用查询到数据库。

我比较了使用for,for-of,while,forEach和reduce的随机数1万项的总和。 运行测试10,000次返回以下结果:

For Loop, average loop time: ~10 microseconds
For-Of, average loop time: ~110 microseconds
ForEach, average loop time: ~77 microseconds
While, average loop time: ~11 microseconds
Reduce, average loop time: ~113 microseconds

在谷歌搜索如何对数组求和时,reduce是提供最好的解决方案,但它是最慢的。 我的首选不是更好。 即使是最新版(ES6)也会提供较差的性能。 事实证明,良好的for循环(还有一段时间)可以提供迄今为止最好的性能-比原来好10倍!

最新和推荐的解决方案如何使JavaScript变慢得多? 造成这种痛苦的原因主要有两个,reduce和forEach要求递归调用该函数以递归方式调用并膨胀堆栈,而对执行的代码进行额外的操作和验证( 在此进行介绍)。

2.复制阵列

虽然这听起来似乎不太有趣,但这是不可变函数的基础,不可变函数在生成输出时不会修改输入。

性能测试结果再次显示出相同的有趣趋势-复制10k数组的10k随机项目时,使用旧式解决方案的速度更快。 同样,最流行的ES6传播操作[[…arr]`和来自Array.from(arr)的Array,再加上ES5映射arr.map(x => x),不如经验丰富的切片arr.slice() `并连接`[] .concat(arr)`。

Duplicate using Slice, average: ~367 microseconds
Duplicate using Map, average: ~469 microseconds
Duplicate using Spread, average: ~512 microseconds
Duplicate using Conct, average: ~366 microseconds
Duplicate using Array From, average: ~1,436 microseconds
Duplicate manually, average: ~412 microseconds

3.迭代对象

另一个常见的情况是遍历对象,这主要在我们尝试遍历JSON和对象且不查找特定键值时是必需的。 同样,还有一些老套的解决方案,例如for-in的for(for obj中的let key),或更高版本的Object.keys(obj)(在es6中呈现)和Object.entries(obj)(在ES8中)。返回键和值。

使用上述方法,对1万个对象迭代(每个实例包含1,000个随机键和值)的性能分析显示了以下内容。

Object iterate For-In, average: ~240 microseconds
Object iterate Keys For Each, average: ~294 microseconds
Object iterate Entries For-Of, average: ~535 microseconds

原因是在后面的两个解决方案中创建了可枚举的值数组,而不是在没有键数组的情况下直接遍历对象。 但是,最终结果仍然令人担忧。

底线

我的结论很清楚-如果要以快速的性能为您的应用程序服务的关键,还是服务器需要处理一些负载-使用最酷,更易读,更干净的选项将对您的应用程序性能产生重大影响-最高可达10时间慢了!

下次,在盲目采用最新趋势之前,请确保它们也符合您的要求-对于小型应用程序而言,编写快速且可读性强的代码是完美的-但是对于压力较大的服务器和大型客户端应用程序,这可能不是最佳做法。

From: https://hackernoon.com/3-javascript-performance-mistakes-you-should-stop-doing-ebf84b9de951