为了账号安全,请及时绑定邮箱和手机立即绑定

揭秘JavaScript引擎:浏览器如何让你的代码活起来

我一直对现代 web 应用背后的深刻抽象概念感到着迷。但是,随着我对 JavaScript 在底层的执行方式有了更多的了解,我对一个更深的话题产生了兴趣——JavaScript 引擎;这些强大的运行时默默地赋予你的 JavaScript 代码生命,在浏览器中运行时,它们还会为你进行所有优化。最近,我一直在研究它们的实现和历史,想分享其中一些最有趣的事实。

这篇帖子介绍了JavaScript引擎如何从解析你的代码到使其运行得更快更高效的过程,构建引擎时常使用的设计模式(这些模式也可以解释为什么某些代码比其他代码快),以及其他一些可以从引擎构建者那里借鉴的建议,来编写更高效的JS代码。

此处省略
此处省略
此处省略

什么是JavaScript引擎?

简单来说,JavaScript引擎就是一个程序,它将你的JavaScript代码转换成计算机可以运行的形式。每个浏览器都有自己的JavaScript引擎,旨在为用户提供最佳体验。

  • V8 :驱动着 Google Chrome 和 Node.js。
  • SpiderMonkey :Mozilla Firefox 的引擎。
  • JavaScriptCore :驱动着 Safari。
  • Chakra :微软 Edge 引擎(在采用 Chromium 之前所使用的)。

这些引擎是使你的代码在各种设备和平台上高效运行的关键。

……

当你在浏览器中运行JavaScript代码时,这里就是每一步会发生的情况。

  • 分析:引擎首先读取(分析)你给它的 JavaScript 代码,并将其转换为计算机可以理解的一系列指令。然后被转换为一种称为“抽象语法树”的数据结构。

例如:读一个食谱,并将它拆分成材料和步骤。

  • 编译过程:现代引擎不会直接从AST运行代码,而是将代码编译成字节码,甚至直接编译成机器代码,这样就可以更快地执行。

关键特性:即时(JIT)编译。在运行过程中,引擎使用即时(JIT)编译技术来优化代码的执行。这意味着这会在运行时根据需求优化正在执行的二进制代码,以提高其运行速度。

  • 执行:一旦编译完成,优化后的机器码就在您的硬件上运行,就是引擎会在执行过程中继续优化。它对程序中经常被执行的部分(称为“热路径”)应用了许多高级优化技术,使其运行得非常快。

……

JavaScript 引擎的关键改进

现代的引擎使用多种技术来保证你的JavaScript代码运行速度快,且节省内存。

即时编译(JIT)

JIT 编译是指引擎在程序运行时编译部分代码。这意味着引擎了解程序实际运行情况,可以据此优化代码。

示例:当一个循环被多次执行时,引擎会将其识别为热点并进行优化以加快执行。

内联缓存机制

在访问对象属性的过程中,引擎首先检查缓存。如果在缓存中找到了,这将减少整体查找时间,因为不必再查找属性的实际所在。

示例:基本上,如果你多次访问 user.name,引擎会记住存储用户数据的对象,以便下次可以直接访问,而无需再查找该对象,就可以直接访问。

垃圾回收

JavaScript 引擎内置了一个叫做垃圾回收器的功能。当它判断一个对象不再被需要时释放内存。

例如,如果你在一个函数里创建了一个对象,而函数结束后你不再需要它,引擎会自动清理不再需要的对象。

……

浏览器怎样使用JavaScript运行时环境

JavaScript引擎与浏览器的渲染引擎并行运行。当你浏览一个网站时,

  • 浏览器首先加载 HTML、CSS 和 JavaScript 文件。
  • 浏览器中的 JavaScript 引擎会解析并运行这些脚本。
  • 渲染引擎将处理后的 HTML、CSS 和 JavaScript 结合起来以展示网页。

例子:

当你访问任何电子商务网站时,比如将商品添加到购物车、更新价格和加载产品详情等功能,都是由JavaScript引擎负责的,丝毫没有重新加载页面。

……

编写友好引擎代码的小技巧

对引擎友好的代码有助于你编写高效的程序,同时也能让程序更易于扩展和维护。这里有一份实用的清单,包含解释和示例,帮助你更好地利用JavaScript引擎的全部功能。

1. 优化 DOM 操作
不必要的频繁 DOM 操作会拖慢你的应用,因为每次更新都会让浏览器重新计算样式并重新渲染元素。

最佳做法:

尽量减少更新DOM,可以采用批处理,使用文档片段或类似React的框架来高效更新。

例如:而是:

图片描述 请点击图片查看

用一个文档片段来操作:

图片描述

为什么这有帮助:通过减少DOM操作,你可以减少重排和重绘,从而使应用更快。

等等

2. 避免在循环和条件中过度嵌套
这会使你的代码更难调试和优化,也会让引擎难以处理深层次的嵌套结构。

最佳做法

将深度嵌套的循环或条件拆分为较小的独立函数。

例如:改为:

图片说明:此处应有一图

用:

这是一张图片:

这怎么有帮助:减少嵌套让代码更易读,使引擎能更高效地优化代码,从而使代码运行得更好。

……

3. 在循环中缓存数组长度
每次你在循环中使用 array.length,引擎就会重新计算数组的长度。这在处理大型数组时可能会引发性能问题。

最佳做法:

在循环开始之前,先计算并存储数组的长度。

例如:而是:

图片说明

用法:

请看这张图片
点击图片查看

为什么这有用:通过存储长度,你可以避免重复计算,让循环运行得更快。


4. 使用现代 JavaScript 的特性和内置方法
现代 JavaScript 的特性和内置方法通常比旧技术更被引擎优化,因此更适合使用。

最佳做法:

  • 请尽量使用 letconst 而不是 var 来声明变量。
  • 当适用时,尽量使用数组方法(如 mapfilterreduce),而不是手动迭代。

例如:而不是

图片说明

用法:

为什么这有用:内置方法高效,让代码更简洁易读。


5. 避免内存泄漏,做好释放工作
内存泄漏发生于不再需要的对象未被释放时,导致内存占用随时间不断增加。

最佳做法:

  • 不应及时在不再需要时才移除事件监听器。
  • 避免不必要的全局变量。

例如:而是:

这是一张图片:图片描述

用法:

图片描述

为什么这有帮助:正确的清理确保释放未使用的资源,防止性能随时间逐渐下降。


6. 使用按需加载处理大文件资源
仅在需要时加载这些资源,以减少应用的启动时间。

最佳做法:

  • 为图片使用 loading="lazy" 属性(例如:<img class="lazyload" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original="image.jpg" loading="lazy">)。
  • 请按需动态加载 JS 模块。

比如:

图片说明

为什么有帮助的是:延迟加载通过延迟加载非必需资源来提升性能。


7. 避免阻塞主进程
JavaScript 运行在一个单独的线程上,所以长时间运行的任务会阻塞 UI,从而使您的应用无法响应。

最佳做法:

可以使用 setTimeoutsetIntervalWeb Workers 来处理那些消耗大量资源的计算任务。

例如:改为:

如需查看图片,请点击此处 点击此处

使用 Web Worker 来:

这是一张图片,你可以在这里查看它: 图片描述

为什么这有帮助:将繁重的任务转移给后台处理可以防止用户界面冻结,确保用户界面操作流畅。


8. 启用内联缓存
JavaScript 引擎通过缓存经常访问的对象属性的位置来优化性能。确保对象的结构保持一致,以获得更好的性能。

最佳做法

尽量不要在对象上动态添加或删除属性。

例如:改为:

图片描述: 请在这里添加描述

用途。

图片描述

为什么有帮助的是:引擎优化具有可预测结构的对象,从而使属性访问速度加快。


9. 减少冗余计算
避免重复执行相同的计算,尤其是在结果可以被缓存时。

最佳做法:

使用记忆化来减少耗时函数的调用。

例如:而不是:

改为:

例如:而是:

图片描述

用法:

图片

为什么有帮助的是:缓存减少了重复计算,提高了递归函数的执行效率。


10. 使用 DevTools 查看并优化代码的性能
使用浏览器的开发者工具来找出并优化拖慢运行速度的代码部分。

最佳做法:

-定期分析应用,找出运行缓慢的部分。
-找出哪些代码运行得慢。
-根据实际使用模式来优化。

示例:使用 Chrome DevTools 的 Performance 标签找到慢脚本或过多重绘,然后根据需要调整你的代码。

有帮助的原因是:剖析会从数据中为你提供见解,并让你知道该在哪部分下功夫优化。


V8 在 Google Chrome 中的角色

Google的V8引擎是目前最先进的JavaScript引擎之一。它驱动着Chrome和Node.js,使得像Gmail、Google Maps和YouTube这样的现代网页应用即使在较慢的机器上也能快速高效地运行。V8通过诸如即时编译和内联缓存等性能优化技术来实现这一目标。


JavaScript 引擎的演进历程

从最初到现在,JavaScript 引擎的发展真是进步了很多!

  • 早些时候:引擎只是直接解释代码,这导致执行速度变慢。
  • JIT 的引入:后来,引擎开始采用 JIT 编译技术,从而提高了运行时性能。
  • 现在的创新:现代引擎采用了诸如 WebAssembly (Wasm) 集成和多线程执行等高级技术,从而实现了卓越的性能。

    • *

最后:

作为开发者,我们花了很多时间编写代码。了解JavaScript引擎是如何执行代码的可以帮助我们编写更好、更优化的应用。当你了解JavaScript引擎具备的能力,比如即时编译、垃圾回收和内联缓存,你就能利用这些优势来设计你的解决方案。

我希望这篇帖子能帮助你理解每当你在浏览器中运行JavaScript时背后的魔法。继续写出更干净、更高效的代码,并认识到JavaScript引擎为让我们的程序更生动所作出的巨大努力。

编程愉快!!! 干杯,祝我们构建更快速更流畅的网页 😊

点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消