优化 JavaScript 执行[转]

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

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

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

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

尽管如此,您肯定还是可以做一些事情来帮助您的应用很好地执行 JavaScript。

  • 对于动画效果的实现,避免使用 setTimeout 或 setInterval,请使用 requestAnimationFrame。
  • 将长时间运行的 JavaScript 从主线程移到 Web Worker。
  • 使用微任务来执行对多个帧的 DOM 更改。
  • 使用 Chrome DevTools 的 Timeline 和 JavaScript 分析器来评估 JavaScript 的影响。

使用 requestAnimationFrame 来实现视觉变化

当屏幕正在发生视觉变化时,您希望在适合浏览器的时间执行您的工作,也就是正好在帧的开头。保证 JavaScript 在帧开始时运行的唯一方式是使用 requestAnimationFrame。

/**
 * If run as a requestAnimationFrame callback, this
 * will be run at the start of the frame.
 */
function updateScreen(time) {
  // Make visual updates here.
}
requestAnimationFrame(updateScreen);

框架或示例可能使用 setTimeout 或 setInterval 来执行动画之类的视觉变化,但这种做法的问题是,回调将在帧中的某个时点运行,可能刚好在末尾,而这可能经常会使我们丢失帧,导致卡顿。

image

事实上,jQuery 目前的默认 animate 行为是使用 setTimeout!强烈建议您打上补丁程序以使用 requestAnimationFrame

降低复杂性或使用 Web Worker

JavaScript 在浏览器的主线程上运行,恰好与样式计算、布局以及许多情况下的绘制一起运行。如果 JavaScript 运行时间过长,就会阻塞这些其他工作,可能导致帧丢失。

因此,您要妥善处理 JavaScript 何时运行以及运行多久。例如,如果在滚动之类的动画中,最好是想办法使 JavaScript 保持在 3-4 毫秒的范围内。超过此范围,就可能要占用太多时间。如果在空闲期间,则可以不必那么斤斤计较所占的时间。

在许多情况下,可以将纯计算工作移到 Web Worker,例如,如果它不需要 DOM 访问权限。数据操作或遍历(例如排序或搜索)往往很适合这种模型,加载和模型生成也是如此。

var dataSortWorker = new Worker("sort-worker.js");
dataSortWorker.postMesssage(dataToSort);

// The main thread is now free to continue working on other things...

dataSortWorker.addEventListener('message', function(evt) {
   var sortedData = evt.data;
   // Update data on screen...
});

并非所有工作都适合此模型:Web Worker 没有 DOM 访问权限。如果您的工作必须在主线程上执行,请考虑一种批量方法,将大型任务分割为微任务,每个微任务所占时间不超过几毫秒,并且在每帧的 requestAnimationFrame 处理程序内运行。

var taskList = breakBigTaskIntoMicroTasks(monsterTaskList);
requestAnimationFrame(processTaskList);

function processTaskList(taskStartTime) {
  var taskFinishTime;

  do {
    // Assume the next task is pushed onto a stack.
    var nextTask = taskList.pop();

    // Process nextTask.
    processTask(nextTask);

    // Go again if there’s enough time to do the next task.
    taskFinishTime = window.performance.now();
  } while (taskFinishTime - taskStartTime < 3);

  if (taskList.length > 0)
    requestAnimationFrame(processTaskList);

}

此方法会产生 UX 和 UI 后果,您将需要使用进度或活动指示器来确保用户知道任务正在被处理。在任何情况下,此方法都不会占用应用的主线程,从而有助于主线程始终对用户交互作出快速响应。

了解 JavaScript 的“帧税”

在评估一个框架、库或您自己的代码时,务必逐帧评估运行 JavaScript 代码的开销。当执行性能关键的动画工作(例如变换或滚动)时,这点尤其重要。

测量 JavaScript 开销和性能情况的最佳方法是使用 Chrome DevTools。通常,您将获得如下的简单记录:
image

如果发现有长时间运行的 JavaScript,则可以在 DevTools 用户界面的顶部启用 JavaScript 分析器:
image

以这种方式分析 JavaScript 会产生开销,因此一定只在想要更深入了解 JavaScript 运行时特性时才启用它。启用此复选框后,现在可以执行相同的操作,您将获得有关 JavaScript 中调用了哪些函数的更多信息:

image

有了这些信息之后,您可以评估 JavaScript 对应用性能的影响,并开始找出和修正函数运行时间过长的热点。如前所述,应当设法移除长时间运行的 JavaScript,或者若不能移除,则将其移到 Web Worker 中,腾出主线程继续执行其他任务。

避免微优化 JavaScript

知道浏览器执行一个函数版本比另一个函数要快 100 倍可能会很酷,比如请求元素的offsetTop比计算getBoundingClientRect()要快,但是,您在每帧调用这类函数的次数几乎总是很少,因此,把重点放在 JavaScript 性能的这个方面通常是白费劲。您一般只能节省零点几毫秒的时间。

如果您开发的是游戏或计算开销很大的应用,则可能属于本指南的例外情况,因为您一般会将大量计算放入单个帧,在这种情况下各种方法都很有用。

简而言之,慎用微优化,因为它们通常不会映射到您正在构建的应用类型。

目录
相关文章
|
1月前
|
JSON JavaScript 前端开发
震惊!JS如何悄无声息追踪你的每一步?揭秘页面访问与关闭的超级上报大法,让数据说话,优化体验不再难!
【8月更文挑战第4天】在Web开发中,跟踪用户行为对提升体验与留存至关重要。本文以在线学习平台为例,介绍如何用JavaScript监听页面访问及关闭,并上报数据。通过`window.onload`监测页面加载,记录用户访问;利用`navigator.sendBeacon`在用户离开时发送少量数据至服务器,无需担心请求失败。需注意隐私合规、性能影响及浏览器兼容性。此技术有助于深入理解用户行为,为产品迭代提供依据。
48 8
|
11天前
|
C# 开发者 测试技术
震惊!Xamarin 竟能如此构建跨平台应用程序,代码共享、界面设计与性能优化全攻略大揭秘!
【8月更文挑战第31天】在移动应用开发领域,跨平台工具日益受到青睐。Xamarin 是一款强大的工具,支持使用 C# 开发适用于 iOS、Android 和 Windows 的应用。通过安装 Visual Studio 或 Visual Studio for Mac,并创建 Xamarin 项目,开发者可以利用丰富的功能和工具进行开发。Xamarin 的主要优势在于代码共享,能够显著提高开发效率。
26 0
|
11天前
|
API UED 开发者
如何在Uno Platform中轻松实现流畅动画效果——从基础到优化,全方位打造用户友好的动态交互体验!
【8月更文挑战第31天】在开发跨平台应用时,确保用户界面流畅且具吸引力至关重要。Uno Platform 作为多端统一的开发框架,不仅支持跨系统应用开发,还能通过优化实现流畅动画,增强用户体验。本文探讨了Uno Platform中实现流畅动画的多个方面,包括动画基础、性能优化、实践技巧及问题排查,帮助开发者掌握具体优化策略,提升应用质量与用户满意度。通过合理利用故事板、减少布局复杂性、使用硬件加速等技术,结合异步方法与预设缓存技巧,开发者能够创建美观且流畅的动画效果。
34 0
|
13天前
|
JavaScript 前端开发 应用服务中间件
Vue.js项目部署与优化:一场从本地到生产环境的华丽蜕变,见证你的应用如何凤凰涅槃,惊艳上线!
【8月更文挑战第30天】作为一名前端开发者,掌握从本地开发环境到生产环境的迁移至关重要。本文将带你了解如何使用 Vue.js 构建和打包应用,确保其在生产环境中流畅运行。首先,通过 `npm run build` 或 `yarn build` 命令生成生产环境文件;接着,配置服务器(如 Nginx)以支持静态文件服务;最后,通过代码分割、资源压缩、CDN 使用、服务端渲染及缓存策略等手段优化应用性能。跟随本文,你将学会如何让 Vue.js 应用在真实环境中表现优异,为用户提供流畅体验。
26 0
|
1月前
|
缓存 负载均衡 JavaScript
Node.js 服务器性能优化
【8月更文挑战第4天】 Node.js 服务器性能优化
33 1
|
2月前
|
缓存 监控 JavaScript
常见的JS优化方案都有那些
【7月更文挑战第7天】 JavaScript优化包括代码优化(箭头函数、解构赋值、模板字面量、展开运算符、高阶函数)、DOM操作优化(减少操作、事件委托、节流防抖)、异步优化(Promise、Web Workers)、缓存策略(结果缓存、HTTP缓存)、压缩合并以及性能分析和监控。通过这些方法,提升网页性能和用户体验。
22 1
|
2月前
|
数据采集 缓存 JavaScript
JavaScript递归函数的设计与优化
JavaScript递归函数的设计与优化
|
2月前
|
数据采集 缓存 JavaScript
JavaScript递归函数的设计与优化
JavaScript递归函数的设计与优化
|
2月前
|
JavaScript 前端开发
前端 JS 经典:Vite 打包优化
前端 JS 经典:Vite 打包优化
131 0
|
3月前
|
前端开发 JavaScript Java
高效前端开发技巧:如何优化JavaScript代码执行效率
在当今互联网应用日益复杂的背景下,前端开发者面临着更高的性能要求。本文探讨了一些提升JavaScript代码执行效率的实用技巧,包括优化循环结构、减少内存占用以及利用现代浏览器的优化能力。通过这些方法,开发者可以在保持代码清晰易读的前提下,显著提升应用程序的响应速度和用户体验。