如何提高前端Web应用程序性能:五个技巧



在我的许多前端项目中,有时会遇到性能下降的情况-这通常是在应用程序复杂性增加时发生的,这是正常的。 尽管如此,开发人员仍然要对性能负责,因此,在我的文章中,我将提供五个优化我自己应用程序的技巧:有些看起来很明显,有些影响编程的基本原理-但是,我认为刷新内存并不是多余的会的。 每个技巧都有测试支持:您可以自己运行它们并测试性能。

翻译成Alconost

前言


请记住:如果代码不需要优化,请不要参与其中。 当然,您编写的代码应该可以快速运行,并且您始终可以提出一种更快的算法-但是编写的代码对于其他开发人员应保持清楚。 在演讲“编程作为一门艺术”中,Donald Knuth表达了关于代码优化的一个非常重要的想法:

真正的问题是程序员花了太多时间在不适当的地方和不适当的时间担心效率。 过早的优化是所有 (或至少大多数)编程错误的根源

1.搜索:代替普通数组-对象和关联数组


在处理数据时,通常会出现以下情况:例如,您需要找到一个对象,对其进行处理,然后再找到另一个对象,依此类推。 JS中最常见的数据结构是数组,因此通常将数据存储在其中。 但是,每当需要在数组中查找内容时,都必须使用诸如“ find”,“ indexOf”,“ filter”或通过循环进行迭代的方法-也就是说,您需要从头到尾对元素进行迭代。 因此,我们执行线性搜索,其复杂度为0(n)(在最坏的情况下,我们将需要执行与数组中存在的元素一样多的比较)。 如果在小型阵列上多次执行此操作,则对性能的影响将很小。 但是,如果我们有很多元素,并且执行了多次操作,则性能肯定会失败。

在这种情况下,将常规数组转换为对象或关联数组并执行键搜索将是一个很好的解决方案:在这些结构中,元素可以O(1)的复杂度进行访问-无论大小如何,我们将有一个内存调用。 通过使用称为哈希表的数据结构可以提高工作速度。

您可以在此处测试性能: https : //jsperf.com/finding-element-object-vs-map-vs-array/1 。 以下是我的结果:



区别非常明显:对于一个关联数组和一个对象,我每秒获得数百万次操作,而对于数组,最佳结果是一百多个操作。 当然,这里不考虑数据转换,但是即使考虑到它的操作也会更快。

2.代替例外-条件运算符“ if”


有时,跳过空检查并捕获相应的异常似乎更容易。 当然,这是一个坏习惯-您不需要这样做,并且如果您的代码中有一个,只需重写相应的部分即可。 但是为了完全说服您,我将通过测试来支持此建议。 我决定测试三种检查方法:表达式“ try-catch”,条件“ if”和“短路”的计算。

测试: https : //jsperf.com/try-catch-vs-conditions/1 。 以下是我的结果:



我认为从这里显而易见,必须检查“空”。 此外,如您所见,“如果”条件与“短路”的计算几乎没有区别-然后适用于灵魂所在。

3.周期越少越好


另一个显而易见但可能有争议的考虑。 数组有许多方便的函数:“ map”,“ filter”,“ reduce”,因此它们的使用看起来很吸引人,并且带有代码的代码看起来更整洁并且更易于阅读。 但是当出现提高生产率的问题时,您可以尝试减少被调用函数的数量。 我决定分析两种情况:1)“过滤器”,然后“映射”,以及2)“过滤器”,然后“减少”-并将它们与功能链,“ forEach”和传统的“ for”循环进行比较。 为什么这两种情况呢? 从测试中可以看出,所获得的好处可能并不十分明显。 另外,在第二种情况下,我在调用“ reduce”时也尝试使用“ filter”。

“过滤器”和“映射”的性能测试: https : //jsperf.com/array-function-chains-vs-single-loop-filter-map/1 。 我的结果:



可以看出,一个周期更快,但差异很小。 如此小的间隙的原因是“推”操作,在使用“地图”时不需要。 因此,在这种情况下,您可以考虑是否真的有必要进行一个循环。

现在,让我们检查“过滤器” +“减少”: https : //jsperf.com/array-function-chains-vs-single-loop-filter-reduce/1 。 我的结果:



这里的差异已经更大:将两个功能组合为一个功能几乎可以将执行速度提高一半。 尽管如此,过渡到传统的“ for”循环仍然可以大大提高速度。

4.使用常规的for循环


该建议似乎也有争议,因为开发人员喜欢功能周期:它们被很好地阅读并且可以简化工作。 但是,它们不如传统周期有效。 我想您可能已经注意到for循环使用的区别,但是让我们在一个单独的测试中看看它: https : //jsperf.com/for-loops-in-few-different-ways/ 。 如您所见,除了内置机制之外,我还检查了“ Lodash”库中的“ forEach”和“ jQuery”中的“ each”。 结果:



再一次,我们看到最简单的“ for”循环比其他循环快得多。 的确,这些循环仅对数组有用-在其他可迭代对象的情况下,应使用“ forEach”,“ for ... of”或迭代器本身。 但是,仅在根本没有其他方法的情况下,才应使用“ for ... in”。 另外,请记住,“ for ... in”接受对象的所有属性(在数组中,属性是索引),这可能导致不可预测的结果。 令人惊讶的是,Lodash和jQuery的方法在性能方面还不错,因此在某些情况下,您可以安全地使用它们而不是内置的“ forEach”(有趣的是,在测试中,Lodash的循环比内置的循环运行得更快)。

5.使用内置函数来处理DOM


有时,您查看别人的代码,发现开发人员仅出于处理DOM的目的而导入了jQuery-我敢肯定您也已经看到了,因为这是最受欢迎的JavaScript库之一。 显然,使用库来控制DOM并没有错:今天,我们使用React和Angular,它们也是如此。 但是,有些人有时甚至将jQuery用于甚至从DOM中提取元素并对其进行较小更改的简单操作也应使用。

这是在三种不同情况下DOM和类似的JQuery操作的内置函数的比较: https : //jsperf.com/native-dom-functions-vs-jquery/1 。 我的结果:



同样,最基本的功能-“ getElementById”和“ getElementsByClassName”-在查看DOM时是最快的。 对于标识符和高级选择器,querySelector也比jQuery快。 而且在仅一种情况下,“ querySelectorAll”比jQuery(通过类名称获取元素)要慢。 有关如何以及如何替换jQuery的更多信息,请参见此处:http: //youmightnotneedjquery.com

显然,如果您已经在使用该库来管理DOM,则强烈建议您坚持使用它-但是,对于简单的情况,内置工具就足够了。

附加材料


这五个技巧将帮助您编写更快的JavaScript代码。 但是,如果您有兴趣阅读有关性能优化的更多信息,这里有一些建议:

1.使用Webpack优化JavaScript包:这是一个非常广泛的主题,但是如果一切都正确完成,则可以大大加快应用程序的加载速度。

2.数据结构,基本算法及其复杂性:许多人认为这只是“一种理论”,但是在第一段中,我们看到了该理论在实践中的工作方式。

3.在jsPerf页面上进行测试:您可以在这里熟悉比较不同的方式来完成JavaScript中相同任务的方式,同时可以看到实践中的一个重要指标-速度差异。

关于翻译

这篇文章由Alconost翻译。

Alconost以70种语言本地化游戏应用程序和网站 。 母语翻译,语言测试,带有API的云平台,持续本地化,24/7项目经理,任何格式的字符串资源。

我们还制作广告和培训视频 -用于销售,图像,广告,培训,预告片,专家,Google Play和App Store的预告片的网站。

了解更多

Source: https://habr.com/ru/post/zh-CN456808/


All Articles