# JS 性能优化

来自《高性能 Js》读后感,加载和执行,数据存取,DOM 编程,算法和流程控制

# 一、加载和执行

管理浏览器中的 JavaScript 代码是个棘手的问题,因为代码执行过程会阻塞浏览器的其他进程,比如用户界面绘制。每次遇到 script 标签,页面都必须停下来等待代码下载(如果是外链文件)并执行,然后继续处理其他部分。尽管如此,还是有几种方法能减少 JavaScript 对性能的影响:

  • body 闭合标签之前,将所有 script 标签放到页面底部。这能确保在脚本执行前页面已经完成了渲染。
  • 合并脚本,页面中的 script 标签越少,加载也就越快,响应也更迅速。无论外链文件还是内嵌脚本都是如此。
  • 有多种无阻塞下载 JavaScript 的方法:
  1. 使用 script 标签的 defer 属性;
  2. 使用动态创建 script 元素来下载并执行代码;
  3. 使用 XHR 对象下载 JavaScript 代码并注入页面中。

# 二、数据存取

在 JavaScript 中,数据存储的位置会对代码整体性能产生重大的影响。数据存储共有 4 种方式:字面量、变量、数组项、对象成员。它们有着各自的性能特点。

  • 访问字面量和局部变量的速度最快,相反,访问数组元素和对象成员相对较慢。
  • 由于局部变量存在于作用域链的起始位置,因此访问局部变量比访问跨作用域变量更快。变量在作用域链中的位置越深,访问所需时间就越长。由于全局变量总处在作用域链的最末端,因此访问速度也是最慢的。
  • 避免使用 with 语句,因为它会改变执行环境作用域链。同样,try-catch 语句中的 catch 子句也有同样的影响,也要小心使用。
  • 嵌套的对象成员会明显影响性能,尽量少用。
  • 属性或方法在原型链中的位置越深,访问它的速度也越慢。
  • 通常来说,你可以通过把常用的对象成员、数组元素、跨域变量保存在局部变量中来改善 JavaScript 性能。

# 三、DOM 编程

访问和操作 DOM 是现代 Web 应用的重要部分。但每次穿越连接 ECMAScript 和 DOM 两个岛屿之间的桥梁,都会被收取“过桥费”。为了减少 DOM 编程带来的性能损失,请记住以下几点:

  • 最小化 DOM 访问次数,尽可能在 JavaScript 端处理。
  • 如果需要多次访问某个 DOM 节点,请使用局部变量存储它的引用。
  • 小心处理 HTML 集合,因为它实时连系着底层文档。把集合的长度缓存到一个变量中,并在迭代中使用它。如果需要经常操作集合,建议把它拷贝到一个数组中。
  • 使用速度更快的 API,比如 querySelectorAll()和 firstElementChild。
  • 要留意重绘和重棑;批量修改样式时,“离线”操作 DOM 树,使用缓存,并减少访问布局信息的次数。
  • 动画中使用绝对定位,使用拖放代理。
  • 使用事件委托来减少事件处理器的数量。

# 四、算法和流程控制

JavaScript 和其他编程语言一样,代码的写法和算法会影响运行时间。与其他语言不同的是,JavaScript 可用资源有限,因此优化技术更为重要。

  • for、while 和 do-while 循环性能特性相当,并没有一种循环类型明显快于或慢于其他类型。
  • 避免使用 for-in 循环,除非你需要循环遍历一个属性数量未知的对象。
  • 改善循环性能的最佳方式是减少每次迭代的运算量和减少循环迭代次数。
  • 通常来说,switch 总是比 if-else 块,但并不总是最佳解决方案。
  • 在判断条件较多时,使用查找表比 if-else 和 switch 更快。
  • 浏览器的调用栈大小限制了递归算法在 JavaScript 中的应用;栈溢出错误会导致其他代码中断运行。
  • 如果你遇到栈溢出错误,可将方法改为迭代算法,或使用 Memoization 来避免重复计算。
Last Updated: 4/1/2024, 4:22:43 PM