15

【动画演示】JavaScript 引擎运行原理

 4 years ago
source link: https://juejin.im/post/5e0d32b45188253aa74a49b5
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client
2020年01月02日 阅读 2599

【动画演示】JavaScript 引擎运行原理

作者:Lydia Hallie

译者:前端小智

来源: dev

点赞再看,养成习惯

本文 GitHub:github.com/qq449245884… 上已经收录,更多往期高赞文章的分类,也整理了很多我的文档,和教程资料。欢迎Star和完善,大家面试可以参照考点复习,希望我们一起有点东西。

JavaScript 很酷,但是 JS 引擎是如何才能理解我们编写的代码呢?作为 JS 开发人员,我们通常不需要自己处理编译器。然而,了解 JS 引擎的基础知识并了解它如何处理JS代码,并将其转换成机器能够理解的东西,绝对是个有益无害的事情。

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

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

16f638eb4bc625eb?imageslim

字节流解码器从已解码的字节流中创建令牌。例如,0066解码为f, 0075u, 006en, 0063c, 0074t, 0069i, 006fo, 006en,后面跟一个空格。就像JS中的function,这是 JS 中的一个保留关键字,它会创建一个标记,并将其发送给解析器。对于字节流的其余部分也是如此。

16f638f28d9145c7?imageslim

该引擎使用两个解析器:预解析器(pre-parser)解析器(parser)。预解析器只提前检查标记,以查看是否有语法错误。这可以减少发现代码中的错误所需的时间,否则解析器稍后就会发现这些错误。

如果没有错误,解析器将根据从字节流解码器接收到的标记创建节点。使用这些节点,它创建了一个抽象语法树,即AST

16f638fae40af03e?imageslim

接下来,轮到解释器(interpreter)了。遍历AST并根据AST包含的信息生成字节码的解释器。一旦字节码完全生成,AST就会被删除,从而清除内存空间。最后,生成的机器码就可以在电脑上运行了。

16f638ffd72680cd?imageslim

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

字节码与生成的类型反馈一起发送到优化编译器(ptimizing compiler)。 优化的编译器接收字节码和类型反馈,并根据这些信息生成高度优化的机器码。

16f6390ed399a7a9?imageslim

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

相反,JS 引擎使用一种称为**内联缓存(inline caching)**的技术。它将代码缓存在内存中,希望将来它会以相同的行为返回相同的值.假设某个函数被调用100次,并且到目前为止总是返回相同的值。它将假设在第101次调用它时也会返回这个值。

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

function sum(a, b) {
    return a + b
}
sum(1,2)
复制代码

执行结果为 3。 下次调用它时,它将假定我们再次使用两个相同数字对其进行调用。

如果假投,那么就不需要动态查找,只需要使用存储在特定内存槽中的结果,该槽已经有一个引用。否则,如果假设不正确,它将反优化代码并恢复到原始字节码,而不是优化后的机器码。

例如,下一次调用它时,我们传递的是字符串而不是数字。因为 JS 是动态类型的,所以这样做不会有任何错误。

function sum(a, b) {
    return a + b
}
sum('1',2)
复制代码

这意味着数字2将被强制转换成字符串,而函数将返回字符串'12'。它返回执行解释的字节码并更新类型反馈。

我希望这篇文章对你有用!当然,在这篇文章中还没有涉及到引擎的更多部分(JS堆,调用堆栈,等等),后续会继续分享。如果你对 JS 的内部机制感兴趣,强烈建议自己可以做一些研究,V8 是开源的,并且有一些很棒的文档说明它是如何工作的。


dev.to/lydiahallie…

代码部署后可能存在的BUG没法实时知道,事后为了解决这些BUG,花了大量的时间进行log 调试,这边顺便给大家推荐一个好用的BUG监控工具 Fundebug


交流

干货系列文章汇总如下,觉得不错点个Star,欢迎 加群 互相学习。

github.com/qq449245884…

我是小智,公众号「大迁世界」作者,对前端技术保持学习爱好者。我会经常分享自己所学所看的干货,在进阶的路上,共勉!

关注公众号,后台回复福利,即可看到福利,你懂的。

1

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK