• JavaScript 性能优化


    更多文章

    加载与执行

    • <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
    • 使用事件委托
    <ul>
      <li>苹果</li>
      <li>香蕉</li>
      <li>凤梨</li>
    </ul>
    
    // 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

  • 相关阅读:
    MIUI(Android)使用Webview上传文件
    使用EntityFramework中DbSet.Set(Type entityType)方法碰到的问题
    Web文件管理:elFinder.Net(支持FTP)
    ASP.NET 根据现有动态页面生成静态Html
    LaTeX学习
    Java Integer剖析
    20140711 loop
    20140711 eat
    20140711 set
    20140710 loop
  • 原文地址:https://www.cnblogs.com/woai3c/p/10250075.html
Copyright © 2020-2023  润新知