JavaScript很酷,然而机器是如何能力真正了解咱们所编写的代码呢?作为JavaScript开发人员,咱们通常不用本人解决编译器。不过,肯定要理解JavaScript引擎的基础知识,看看它如何解决咱们对人类敌对的JS代码,并将其转换成机器能够了解的货色!????

请留神:这篇文章次要基于Node.js和基于Chromium的浏览器应用的V8引擎。


HTML解析器遇到script标记,代码从网络缓存或已装好的service worker加载。响应是把申请的脚本作为字节流,由字节流解码器负责!字节流解码器在下载字节流时对其进行解码。





字节流解码器从被解码的字节流中创立标记(token)。比方,0066解码为f0075解码为u006e解码为n0063解码为c0074解码为t0069解码为i006f解码为o006e解码为n,前面跟一个空格。这不就是咱们代码中写的function么!这是JavaScript中的一个保留关键字,会创立一个标记,并发送给解析器(和_预解析器_,这在gif中没有介绍,但稍后会解释)。字节流的其余部分也是这样的。





引擎应用两个解析器:预解析器(Pre-Parser)解析器(Parser)。为了缩小加载网站所需的工夫,引擎尝试防止解析不须要立刻执行的代码。预处理器解决稍后可能应用的代码,而解析器解决立刻须要的代码!如果某个函数只在用户单击按钮后才被调用,那么就没有必要立刻编译这段代码来加载到网站。如果用户最终单击按钮并须要这段代码,它才被发送到解析器。


解析器依据从字节流解码器接管的标记创立节点,并用这些节点创立一个形象语法树或AST(Abstract Syntax Tree)。????





接下来,该解释器(Interpreter)出场了! 解释器遍历AST,并依据AST所蕴含的信息生成字节码。字节码生成结束后,会删除AST,以革除内存空间。最初,咱们就有了一些机器能够解决的货色了!????


[


只管字节码很快,然而它还能够更快点。随着此字节码运行,会生成一些信息。它能够检测某些行为是否常常产生,以及所应用的数据类型。可能咱们曾经调用了某个函数几十次数:该对它进行优化,让它运行得更快了!????????♀️


字节码与生成的类型反馈一起,被发送到优化编译器。优化编译器获取字节码和类型反馈,并从中生成高度优化过的机器码。  ????


[


JavaScript是一种动静类型的语言,这意味着数据的类型能够一直变动。如果JavaScript引擎每次都得查看某个值是哪种数据类型,那就会十分慢。


为了缩小解释代码所需的工夫,优化过的机器码仅解决在执行字节码时引擎曾经见过的状况。如果咱们重复应用某段重复返回雷同数据类型代码,那么就能够简略地从新应用通过优化的机器码以放慢处理速度。不过,因为JavaScript是动静类型的,所以可能会产生同样的代码忽然返回不同类型的数据的状况。如果产生这种状况,引擎就会对机器码进行非最佳化,并且会退回到解释生成的字节码。


如果某个函数被调用了100次,并且到目前为止始终返回雷同的值,引擎就会假如在第101次调用它时还将返回该值。


假如咱们有如下函数sum,(到目前为止)每次都应用数值作为参数来调用它:





这段代码会返回数字3! 下次调用它时,引擎就会假设咱们再次应用两个数值对其进行调用。


如果是这样,就无需进行动静查找,而只需重用优化过的机器码就能够了。否则,如果假如不正确,它将复原为原始字节码,而不是优化过的机器码。


比方,下一次调用它时,咱们传递的是字符串而不是数字。因为JavaScript是动静类型的,所以咱们能够做到这一点而没有任何谬误!





这意味着数字2会被强制转换为字符串,并且函数将返回字符串12。引擎会回过来执行解释过的字节码,并更新类型反馈。


心愿这篇文章对您有用! ????当然,我在这篇文章中没有波及引擎的很多局部(JS堆、调用栈等),我稍后可能会波及! 如果您对JavaScript的外部机制感兴趣,我相对激励您本人开始做一些钻研,V8是开源的,并且有一些不错的文档阐明其工作原理!????


V8 Docs || V8 Github || Chrome University 2018: Life Of A Script

原文 by Lydia Hallie:https://dev.to/lydiahallie/javascript-visualized-the-javascript-engine-4cdf
本文由博客一文多发平台 OpenWrite 公布!