JavaScript 性能优化

Stella981
• 阅读 360

更多文章

加载与执行

  • <script>标签放在</body>前面,不要放在<head>中,防止造成堵塞
  • 尽量减少请求,单个100KB的文件比4个25KB的文件更快,也就是说减少页面中外链的文件会改善性能
  • 尽量使用压缩过的JS文件,体积更小,加载更快

数据存取

  • 使用局部变量和字面量比使用数组和对象有更少的读写消耗
  • 尽可能使用局部变量代替全局变量
  • 如无必要,不要使用闭包;闭包引用着其他作用域的变量,会造成更大的内存开销
  • 原型链不要过深、对象嵌套不要太多
  • 对于多次访问的嵌套对象,应该用变量缓存起来

DOM编程

  • 不要频繁修改DOM,因为修改DOM样式会导致重绘(repaint)和重排(reflow)

  • 如果要修改DOM的多个样式可以用cssText一次性将要改的样式写入,或将样式写到class里,再修改DOM的class名称

    const el = document.querySelector('.myDiv') el.style.borderLeft = '1px' el.style.borderRight = '2px' el.style.padding = '5px'

可以使用如下语句代替

const el = document.querySelector('.myDiv')
el.style.cssText = 'border-left: 1px; border-right: 2px; padding: 5px;'

cssText会覆盖已存在的样式,如果不想覆盖已有样式,可以这样

el.style.cssText += ';border-left: 1px; border-right: 2px; padding: 5px;'
  • 避免大量使用:hover

  • 使用事件委托

    • 苹果
    • 香蕉
    • 凤梨

    // good document.querySelector('ul').onclick = (event) => { let target = event.target if (target.nodeName === 'LI') { console.log(target.innerHTML) } }

    // bad document.querySelectorAll('li').forEach((e) => { e.onclick = function() { console.log(this.innerHTML) } })

批量修改DOM

当你需要批量修改DOM时,可以通过以下步骤减少重绘和重排次数:

  1. 使元素脱离文档流
  2. 对其应用多重改变
  3. 把元素带回文档中

该过程会触发两次重排——第一步和第三步。如果你忽略这两个步骤,那么在第二步所产生的任何修改都会触发一次重排。

有三种方法可以使DOM脱离文档:

  • 隐藏元素,应用修改,重新显示
  • 使用文档片断(document.fragment)在当前DOM之外构建一个子树,再把它拷回文档
  • 将原始元素拷贝到一个脱离文档的节点中,修改副本,完成后再替换原始元素

算法和流程控制

  • 改善性能最佳的方式是减少每次迭代的运算量和减少循环迭代次数

  • JavaScript四种循环中for while do-while for-in,只有for-in循环比其他其中明显要慢,因为for-in循环要搜索原型属性

  • 限制循环中耗时操作的数量

  • 基于函数的迭代forEach比一般的循环要慢,如果对运行速度要求很严格,不要使用

  • if-else switch,条件数量越大,越倾向于使用switch

  • 在判断条件多时,可以使用查找表来代替if-else switch,速度更快

    switch(value) { case 0: return result0 break case 1: return result1 break case 2: return result2 break case 3: return result3 break }

    // 可以使用查找表代替 const results = [result0, result1, result2, result3]

  • 如果遇到栈溢出错误,可以使用迭代来代替递归

字符串

str += 'one' + 'two'

此代码运行时,会经历四个步骤:

  1. 在内存中创建一个临时字符串

  2. 连接后的字符串 onetwo 被赋值给该临时字符串

  3. 临时字符串与str当前的值连接

  4. 结果赋值给str

    str += 'one' str += 'two'

第二种方式比第一种方式要更快,因为它避免了临时字符串的产生

你也可以用一个语句就能达到同样的性能提升

str = str + 'one' + 'two'

快速响应用户界面

  • 对于执行时间过长的大段代码,可以使用setTimeoutsetInterval来对代码进行分割,避免对页面造成堵塞
  • 对于数据处理工作可以交由Web Workers来处理,因为Web Workers不占用浏览器UI线程的时间

编程实践

  • 使用Object/Array字面量

    const obj = new Object() const newObj = {}

    const arry = new Array() const newArry = []

使用字面量会运行得更快,并且节省代码量

  • 位操作在JavaScript中性能非常快,可以使用位运算来代替纯数学操作

    x =* x // 用位运算代替 x <<= 1

  • 如无必要,不要重写原生方法,因为原生方法底层是用C/C++实现的,速度更快

参考资料

高性能JavaScript

本文同步分享在 博客“谭光志”(SegmentFault)。
如有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。

点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
待兔 待兔
4个月前
手写Java HashMap源码
HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22
Jacquelyn38 Jacquelyn38
3年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
Stella981 Stella981
3年前
Opencv中Mat矩阵相乘——点乘、dot、mul运算详解
Opencv中Mat矩阵相乘——点乘、dot、mul运算详解2016年09月02日00:00:36 \牧野(https://www.oschina.net/action/GoToLink?urlhttps%3A%2F%2Fme.csdn.net%2Fdcrmg) 阅读数:59593
Stella981 Stella981
3年前
Android So动态加载 优雅实现与原理分析
背景:漫品Android客户端集成适配转换功能(基于目标识别(So库35M)和人脸识别库(5M)),导致apk体积50M左右,为优化客户端体验,决定实现So文件动态加载.!(https://oscimg.oschina.net/oscnet/00d1ff90e4b34869664fef59e3ec3fdd20b.png)点击上方“蓝字”关注我
Wesley13 Wesley13
3年前
mysql设置时区
mysql设置时区mysql\_query("SETtime\_zone'8:00'")ordie('时区设置失败,请联系管理员!');中国在东8区所以加8方法二:selectcount(user\_id)asdevice,CONVERT\_TZ(FROM\_UNIXTIME(reg\_time),'08:00','0
Wesley13 Wesley13
3年前
00:Java简单了解
浅谈Java之概述Java是SUN(StanfordUniversityNetwork),斯坦福大学网络公司)1995年推出的一门高级编程语言。Java是一种面向Internet的编程语言。随着Java技术在web方面的不断成熟,已经成为Web应用程序的首选开发语言。Java是简单易学,完全面向对象,安全可靠,与平台无关的编程语言。
Stella981 Stella981
3年前
Google地球出现“无法连接到登录服务器(错误代码:c00a0194)”解决方法
Google地球出现“无法连接到登录服务器(错误代码:c00a0194)”解决方法参考文章:(1)Google地球出现“无法连接到登录服务器(错误代码:c00a0194)”解决方法(https://www.oschina.net/action/GoToLink?urlhttps%3A%2F%2Fwww.codeprj.com%2Fblo
Wesley13 Wesley13
3年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
Python进阶者 Python进阶者
10个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这