javascript可视化,javascript引擎

495 阅读4分钟

首次翻译英文博客,如果有任何意见建议请在下方评论区联系我

原文链接

img

JavaScript很酷,机器是如何理解我们前端人员编写的js代码呢?作为JavaScript开发人员,我们通常不需要自己处理编译器。不过,了解JavaScript引擎的基本知识,看看它是如何处理我们编写的JS代码的,并把它变成机器能理解的东西,绝对是件好事!

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

HTML解析器遇到一个带有js代码的script标签。将会从networkcacheserviceworker加载此源代码。响应体(response)是作为字节流的请求脚本,字节流解码器负责处理!字节流解码器在下载字节流时对其进行解码。

img2

字节流解码器从已解码的字节流进行解析。例如,0066解码为f,0075解码为u,006e解码为n,0063解码为c,0074解码为t,0069解码为i,006f解码为o,006e解码为n,后跟空格。这就是我们写的function!这是JavaScript中的一个保留关键字,创建一个token,并发送给解析器(parser)和预解析器(pre-parser)。字节流的其余部分也是如此。

img3
引擎使用两个解析器:预解析器和解析器。预解析器只在早期检查标记以查看是否存在语法错误。这可以减少在代码中发现错误所需的时间,否则解析器稍后将发现这些错误! 如果没有错误,解析器根据从字节流解码器接收到的token创建节点。使用这些节点,它创建一个抽象语法树(AST)。
img4

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

img5

虽然字节码很快,但它可以更快。当这个字节码运行时,将生成信息。它可以检测某些行为是否经常发生,以及所使用的数据类型。也许你已经调用函数几十次了:是时候优化它了,这样它会运行得更快!

字节码和生成的类型反馈一起发送给优化编译器。优化编译器接受字节码和类型反馈,并从中生成高度优化的机器代码。

img6
JavaScript是一种动态类型语言,意味着数据类型可以不断变化。如果JavaScript引擎每次都要检查某个值所具有的数据类型,那么速度会非常慢。

相反,引擎使用一种称为内联缓存的技术。它将代码缓存在内存中,希望将来能以相同的行为返回相同的值!假设某个函数被调用了100次,并且到目前为止始终返回相同的值。它将假设在您第101次调用它时它也将返回这个值。

假设我们有以下函数sum,即(到目前为止)每次调用时都使用数值作为参数:

img7
这将返回数字3!下一次调用它时,它将假定我们再次调用它时使用两个数值。

如果这是真的,则不需要动态查找,它只需使用存储在其已引用的特定内存插槽中的结果。否则,如果假设不正确,它将取消对代码的优化,并返回到原始字节代码,而不是优化的机器代码。

例如,下次调用它时,我们传递的是字符串而不是数字。因为JavaScript是动态类型的,所以我们可以做到这一点而不会出现任何错误!

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