javascript图解之JavaScript引擎

本文深入剖析JavaScript引擎的工作原理,从HTML解析器如何处理脚本标记,到V8引擎如何将JS代码转换为机器可读的字节码,再到字节码如何优化为高效机器代码。通过了解JavaScript的编译和执行过程,揭示了动态类型语言如何在速度和灵活性之间找到平衡。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

JavaScript很酷,但是机器怎么能真正理解您编写的代码呢?作为JavaScript开发人员,我们通常不需要自己处理编译器。不过,了解JavaScript引擎的基本知识,看看它如何处理我们人性化的JS代码,并将其转化为机器能够理解的东西,这绝对是件好事!🥳

注意:本文主要基于Node.js和Chromium浏览器使用的V8引擎。

HTML解析器遇到一个带有源代码的脚本标记。来自此源的代码从网络、缓存或已安装的服务工作程序加载。响应是作为字节流的请求脚本,字节流解码器负责处理!字节流解码器在下载字节流时对其进行解码。

字节流解码器从已解码的字节流创建token。例如,0066解码为f,0075解码为u,006e解码为n,0063解码为c,0074解码为t,0069解码为i,006f解码为o,006e解码为n,后跟空格。好像是你写的函数!这是JavaScript中的一个保留关键字,创建一个token,并发送给解析器(和pre-parser,我在gifs中没有介绍,稍后会解释)。字节流的其余部分也是如此。

引擎使用两个解析器:预解析器和解析器。为了减少加载网站所需的时间,该引擎尝试避免分析不需要立即执行的代码。preparser处理稍后可能使用的代码,而解析器处理立即需要的代码!如果某个函数只在用户单击某个按钮后才被调用,则不需要立即编译该代码来加载网站。如果用户最终点击按钮并需要这段代码,它就会被发送到解析器。
解析器基于从字节流解码器接收的token创建节点。使用这些节点,它创建一个抽象语法树(AST)。🌳

接下来,是翻译的时候了!这个解释器遍历AST,并根据AST包含的信息生成字节码。一旦字节码完全生成,AST就会被删除,从而清除内存空间。最后,我们有一个机器可以使用的东西!🎉

虽然字节码很快,但它可以更快。当这个字节码运行时,将生成信息。它可以检测某些行为是否经常发生,以及所使用的数据类型。也许你已经调用函数几十次了:是时候优化它了,这样它会运行得更快!🏃🏽‍♀️
字节码和生成的类型反馈一起发送给优化编译器。优化编译器接受字节码和类型反馈,并从中生成高度优化的机器代码。🚀

JavaScript是一种动态类型语言,意味着数据类型可以不断变化。如果JavaScript引擎每次都要检查某个值所具有的数据类型,那么速度会非常慢。
为了减少解释代码所需的时间,优化的机器代码只处理引擎在运行字节码时看到的情况。如果我们反复使用一段返回相同数据类型的代码,优化后的机器代码就可以简单地重用,以加快速度。然而,由于JavaScript是动态类型的,所以同一段代码可能会突然返回不同类型的数据。如果发生这种情况,机器代码将被取消优化,引擎将返回到解释生成的字节码。
假设某个函数被调用了100次,并且到目前为止始终返回相同的值。它将假设在您第101次调用它时它也将返回这个值。
假设我们有以下函数sum,即(到目前为止)每次调用时都使用数值作为参数:

这将返回数字3!下一次调用它时,它将假定我们再次调用它时使用两个数值。
如果这是真的,那么不需要动态查找,它只需要重用优化的机器代码。否则,如果假设不正确,它将返回到原始字节码,而不是优化的机器码。
例如,下次调用它时,我们传递的是字符串而不是数字。因为JavaScript是动态类型的,所以我们可以做到这一点而不会出现任何错误!

这意味着数字2将被强制为字符串,而函数将返回字符串“12”。它返回到执行解释的字节码并更新类型反馈。
我希望这篇文章对你有用!😊 当然,在这篇文章(JS堆、调用堆栈等)中,我可能会涉及到引擎的许多部分!如果你对JavaScript的内部特性感兴趣的话,我绝对鼓励你自己开始做一些研究,V8是开源的,并且有一些关于它如何在幕后工作的优秀文档!🤖

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值