资讯专栏INFORMATION COLUMN

个人常用JavaScript及React常用优化总结

yuanxin / 599人阅读

摘要:插件性能优化及个人常用优化方法经常会触发视觉变化。作用域链指的是当前作用于下可用变量的集合,它在各种主流浏览器中至少包含两个部分局部变量的集合和全局变量的集合。在考虑优化时,数值和变量的性能差不多,并且速度显著优于对象属性和数组元素。

JavaScript 插件性能优化及个人react常用优化方法

JavaScript 经常会触发视觉变化。有时是直接通过样式操作,有时是会产生视觉变化的计算,例如搜索数据或将其排序。时机不当或长时间运行的 JavaScript 可能是导致性能问题的常见原因。您应当设法尽可能减少其影响。

JavaScript 性能分析可以说是一门艺术,因为您编写的 JavaScript 代码与实际执行的代码完全不像。现代浏览器使用 JIT 编译器和各种各样的优化和技巧来尝试为您实现尽可能快的执行,这极大地改变了代码的动态。

注:如果您真的想了解 JIT 的实例,应当查看 Vyacheslav Egorov 提供的 IRHydra2。它显示了当 Chrome 的 JavaScript 引擎 V8 对 JavaScript 代码进行优化时,JavaScript 代码的中间状态。

尽管如此,您肯定还是可以做一些事情来帮助您的应用很好地执行 JavaScript。但 Javascript 性能优化绝不是一种书面的技术,借鉴别人的意见和自己平时项目的总结给出以下几条建议:

变量问题

当一个变量被引用的时候,JavaScript将在作用域链中的不同成员中查找这个变量。作 用域链指的是当前作用于下可用变量的集合,它在各种主流浏览器中至少包含两个部分:局部变量的集合和全局变量的集合。

简单地说,如果JavaScript引擎在作用域链中搜索的深度越大,那么操作也就会消耗更多的时间。引擎首先从 this 开始查找局部变量,然后是函数参数、本地定义的变量,最后遍历所有的全局变量。

因为局部变量在这条链的起端,所以查找局部变量总是比查找全局变量要块。所以当你想要不止一次地使用一个全局变量的时候,你应该将它定义成局部变量,就像这样:

var dom1 = document.getElementById("id1"),
dom2 = document.getElementById("id2");

改写成

var document = document,
demo1 = document.getElementById("id1"),
demo2 = document.getElementById("id2");
小心的使用闭包

虽然你可能还不知道“闭包”,但你可能在不经意间经常使用这项技术。闭包基本上被认为是JavaScript中的new,当我们定义一个即时函数的时候,我们就使用了闭包,比如:

document.getElementById("dom").onclick = function(ev) { };

闭包的问题在于:根据定义,在它们的作用域链中至少有三个对象:闭包变量、局部变量和全局变量。这些额外的对象将会导致第1和第2个建议中提到的性能问题。

闭包对于提高代码可读性等方面还是非常有用的,只是不要滥用它们(尤其在循环中)。

对象的属性和数组元素影响

谈到JavaScript的数据,一般来说有4种访问方式:数值、变量、对象属性和数组元素。在考虑优化时,数值和变量的性能差不多,并且速度显著优于对象属性和数组元素。

因此当你多次引用一个对象属性或者数组元素的时候,你可以通过定义一个变量来获得性能提升。(这一条在读、写数据时都有效)

虽然这条规则在绝大多数情况下是正确的,但是Firefox在优化数组索引上做了一些有意思的工作,能够让它的实际性能优于变量。但是考虑到数组元素在其他浏览器上的性能弊端,还是应该尽量避免数组查找,除非你真的只针对于火狐浏览器的性能而进行开发。

不要乱碰DOM

不使用DOM是JavaScript优化中另一个很大的话题。经典的例子是添加一系列的列表项:如果你把每个列表项分别加到DOM中,肯定会比一次性加入所有列表项到DOM中要慢。这是因为DOM操作开销很大。

Zakas对这个进行了细致的讲解,解释了由于回流(reflow)的存在,DOM操作是非常消耗资源的。回流通常被理解为浏览器重新选渲染DOM树的处理过程。比如说,如果你用JavaScript语句改变了一个div的宽度,浏览器需要重绘页面来适应变化。

任何时候只要有元素被添加到DOM树或者从DOM树移除,都会引发回流。使用一个非常方便的JavaScript对象可以解决这个问题——documentFragment,我并没有使用过,但是在Steve Souders也表示同意这种做法之后我感觉更加肯定了。

DocumentFragment 基本上是一种浏览器以非可视方式实现的类似文档的片段,非可视化的表现形式带来了很多优点,最主要的是你可以在 documentFragment 中添加任何结点而不会引起浏览器回流。

不要在数组中挖得太深

另外,程序员应该避免在数组中挖得太深,因为进入的层数越多,操作速度就越慢。

简单地说,在嵌套很多层的数组中操作很慢是因为数组元素的查找速度很慢。试想如果操作嵌套三层的数组元素,就要执行三次数组元素查找,而不是一次。

因此如果你不断地引用 foo.bar, 你可以通过定义 var bar = foo.bar 来提高性能。

定时器的使用

如果针对的是不断运行的代码,不应该使用setTimeout,而应该是用setInterval,因为setTimeout每一次都会初始化一个定时器,而setInterval只会在开始的时候初始化一个定时器。

        var timeoutTimes = 0;
        function timeout() {
            timeoutTimes++;
            if (timeoutTimes < 10) {
                setTimeout(timeout, 10);
            }
        }
        timeout();
        //可以替换为:
        var intervalTimes = 0;
        function interval() {
            intervalTimes++;
            if (intervalTimes >= 10) {
                clearInterval(interv);
            }
        }
        var interv = setInterval(interval, 10);
React上的性能优化

对于小型react前端应用,最好的优化就是不优化因为React本身就是通过比较虚拟DOM的差异,从而对真实DOM进行最小化操作,小型React应用的虚拟DOM结构简单,虚拟DOM比较的耗时可以忽略不计。而对于复杂的前端项目,我们所指的渲染性能优化,实际上是指,在不需要更新DOM时,如何避免虚拟DOM的比较。

react组件的生命周期

工欲善其事,必先利其器。理解react的组件的生命周期是优化其渲染性能的必备前提。我们可以将react组件的生命周期分为3个大循环:挂载到DOM、更新DOM、从DOM中卸载。React对三个大循环中每一步都暴露出钩子函数,使得我们可以细粒度地控制组件的生命周期。

挂载到DOM

组件首次插入到DOM时,会经历从属性和状态初始化到DOM渲染等基本流程,可以通过下图所示

必须注意的是,挂载到DOM流程在组件的整个生命周期只有一次,也就是组件第一次插入DOM文档流时。在挂载到DOM流程中的每一步也有相应的限制:

更新DOM

 组件挂载到DOM后,一旦其props和state有更新,就会进入更新DOM流程。同样我们也可以通过一张图清晰的描述该流程的各个步骤:
//getDefaultProps()和getInitialState()中不能获取和设置组件的state。
//render()方法中不能设置组件的state。

componentWillReceiveProps()提供了该流程中更新state的最后时机,后续的其他函数都不能再更新组件的state了。我们尤其需要注意的是shouldComponentUpdate函数,它的结果直接影响该组件是不是需要进行虚拟DOM比较,我们对组件渲染性能优化的基本思路就是:在非必要的时候将shouldComponentUpdate返回值设置为false,从而终止更新DOM流程中的后续步骤。

从DOM中卸载

 从DOM中卸载的流程比较简单,React只暴漏出componentWillUnmount,该函数使得我们可以在DOM卸载的最后时机对其进行干预。

2、性能分析

   合理的使用shouldComponentUpdate()可以在很大程序上优化应用。但在实际情况下,应用往往在沙箱或是开发环境中运行的非常快,但生产环境则表现的不尽人意。这时,我们需要对应用进行性能分析,然后再有针对性的在shouldComponentUpdate()中进行优化。

React 提供了性能分析插件React.addons.Perf,它让我们可以在需要检测的代码起始位置分别添加Perf.start()和Perf.stop(),并可以通过Perf.printInclusive()方法打印花费时间,然后我们可以结合数据做进一步的分析。

React.addons.Perf插件的详细用法,可以查看官方文档。

3、 借助react Key标识组件

key属性在组件类之外提供了另一种方式的组件标识。通过key标识我们可以组件如:顺序改变、不必要的子组件更新等情况下,告诉React 避免不必要的渲染而避免性能的浪费。

如,对于如一个基于排序的组件渲染

var items = sortBy(this.state.sortingAlgorithm, this.props.items);
return items.map(function(item){
  return 
});

当顺序发生改变时,React 会对元素进行diff操作,并改img的src属性。显示,这样的操作效率是非常低的。这时,我们可以为组件添加一个key属性以唯一的标识组件:

    return 

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/82014.html

相关文章

  • 前端资源系列(4)-前端学习资源分享&前端面试资源汇总

    摘要:特意对前端学习资源做一个汇总,方便自己学习查阅参考,和好友们共同进步。 特意对前端学习资源做一个汇总,方便自己学习查阅参考,和好友们共同进步。 本以为自己收藏的站点多,可以很快搞定,没想到一入汇总深似海。还有很多不足&遗漏的地方,欢迎补充。有错误的地方,还请斧正... 托管: welcome to git,欢迎交流,感谢star 有好友反应和斧正,会及时更新,平时业务工作时也会不定期更...

    princekin 评论0 收藏0
  • 个人分享--web前端学习资源分享

    摘要:前言月份开始出没社区,现在差不多月了,按照工作的说法,就是差不多过了三个月的试用期,准备转正了一般来说,差不多到了转正的时候,会进行总结或者分享会议那么今天我就把看过的一些学习资源主要是博客,博文推荐分享给大家。 1.前言 6月份开始出没社区,现在差不多9月了,按照工作的说法,就是差不多过了三个月的试用期,准备转正了!一般来说,差不多到了转正的时候,会进行总结或者分享会议!那么今天我就...

    sherlock221 评论0 收藏0
  • 2017年1月前端月报

    摘要:平日学习接触过的网站积累,以每月的形式发布。年以前看这个网址概况在线地址前端开发群月报提交原则技术文章新的为主。 平日学习接触过的网站积累,以每月的形式发布。2017年以前看这个网址:http://www.kancloud.cn/jsfron... 概况 在线地址:http://www.kancloud.cn/jsfront/month/82796 JS前端开发群月报 提交原则: 技...

    FuisonDesign 评论0 收藏0

发表评论

0条评论

yuanxin

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<