We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? # to your account
本文翻译自🚀⚙️ JavaScript Visualized: the JavaScript Engine
作为JavaScript开发者,我们不需要编译自己编写的代码。那么,JavaScript引擎到底怎么处理这些JS代码,转换成机器能懂的东西呢?🥳
JavaScript
JS
注意:本文主要是基于Node.js的V8引擎和基于Chromium内核的浏览器。
Node.js
V8
Chromium
通过script标签,HTML解析器识别到javascript代码。
script
HTML
javascript
javascript代码要么来自网络,要么来自缓存,或者安装的service worker
service worker
请求的脚本会作为字节流,当在下载字节流时,字节流解码器(Byte Stream Decoder)会将其解码。
字节流解码器将从已经解码的字节流中生成tokens。比如,0066解码为f,0075解码为u,006e解码为n,0063解码为c,0074解码为t,0069解码为i,006f解码为o,006e解码为n。这就是你输入的function!
0066
f
0075
u
006e
n
0063
c
0074
t
0069
i
006f
o
function
然后将这些tokens传送到语法分析器(parser)和预语法分析器(pre-parser)。
tokens
👀下面的gif图并没有表现出pre-parser,后面会提及到
引擎使用两种语法分析器:pre-parse和parse。为了减少网站的加载时间,引擎会避免马上分析没必要的代码。
pre-parse
parse
parser会分析立刻需要用到的代码,而pre-parser处理之后将会用到的代码。比如一个函数只有在用户点击按钮才会触发,那就没必要将那段代码立马进行编译以加载网站。
基于字节流解码器传过来的tokens,语法分析器会创建nodes节点,这些节点形成一个抽象语法树Abstract Syntax Tree (AST)🌳。
nodes
Abstract Syntax Tree (AST)
接着,Interpreter(解释器)会遍历AST,然后基于AST包含的信息生成字节码。字节码生成之后,AST会被删除,对应的内存空间被清理。最后会处理成机器能识别的内容。
AST
虽然字节码运行很快了,但是它可以更快。当字节码运行,相关信息就会生成,它可以检测某些行为是否经常发生,以及使用的数据类型。可能你重复调用一个函数多次:那是时候需要进行优化了,这样会跑得更快!🏃🏽♀️
字节码和生成的类型反馈会一起发送到优化编译器。优化编译器获取字节码和类型反馈,并从中生成高度优化的机器码。🚀
JavaScript是一门动态类型语言,这意味着数据类型可以不停地更改。如果JavaScript引擎必须每次去检查数据类型对应的值,那将会很慢。
为了减少解析代码的时间,优化机器码只处理引擎在运行字节码时见过的情况。如果我们反复使用一段代码,一遍又一遍地返回相同地数据类型,那么可以简单地重复使用经过优化的机器代码以加快处理速度。然而,因为JavaScript是动态类型的。同一片段的代码有可能突然就返回了不同类型的数据。如果发生这种情况,机器码会被进行非最佳化,引擎会回退到解析生成的字节码。
假设一个特定的函数到目前为止,已经被调用了100次并返回相同的值。那么引擎会认为在第101次,你调用它的时候,它也将返回这个值。
假设我们有下面这个求和函数,到目前为止,我们一直以数字作为参数来调用它:
上图两数和返回的是数值3!那么下一次我们调用它,它还会假设我们是通过两个数字类型的数值来调用它。
3
如果上面假设是真的,那么无需进行动态查找了,重复使用经过优化的机器码即可。否则,上面假设不成功的话,它将恢复为原始的字节码,而不是优化的机器码。
比如,我们下次调用sum函数,传递的参数其中一个是字符串,而不是数字。因为JavaScript是动态类型的,所以我们这样做没什么问题。
sum
上图代码中,意味着数字2将会被强制转换成字符串类型,函数返回字符串12。引擎已经回到执行解析字节码并更新类型反馈的阶段了。
2
12
原文:https://dev.to/lydiahallie/javascript-visualized-the-javascript-engine-4cdf
更多内容:https://github.com/reng99
The text was updated successfully, but these errors were encountered:
No branches or pull requests
作为
JavaScript
开发者,我们不需要编译自己编写的代码。那么,JavaScript
引擎到底怎么处理这些JS
代码,转换成机器能懂的东西呢?🥳通过
script
标签,HTML
解析器识别到javascript
代码。请求的脚本会作为字节流,当在下载字节流时,字节流解码器(Byte Stream Decoder)会将其解码。
字节流解码器将从已经解码的字节流中生成tokens。比如,
0066
解码为f
,0075
解码为u
,006e
解码为n
,0063
解码为c
,0074
解码为t
,0069
解码为i
,006f
解码为o
,006e
解码为n
。这就是你输入的function
!然后将这些
tokens
传送到语法分析器(parser)和预语法分析器(pre-parser)。引擎使用两种语法分析器:
pre-parse
和parse
。为了减少网站的加载时间,引擎会避免马上分析没必要的代码。parser会分析立刻需要用到的代码,而pre-parser处理之后将会用到的代码。比如一个函数只有在用户点击按钮才会触发,那就没必要将那段代码立马进行编译以加载网站。
基于字节流解码器传过来的
tokens
,语法分析器会创建nodes
节点,这些节点形成一个抽象语法树Abstract Syntax Tree (AST)
🌳。接着,Interpreter(解释器)会遍历
AST
,然后基于AST
包含的信息生成字节码。字节码生成之后,AST
会被删除,对应的内存空间被清理。最后会处理成机器能识别的内容。虽然字节码运行很快了,但是它可以更快。当字节码运行,相关信息就会生成,它可以检测某些行为是否经常发生,以及使用的数据类型。可能你重复调用一个函数多次:那是时候需要进行优化了,这样会跑得更快!🏃🏽♀️
字节码和生成的类型反馈会一起发送到优化编译器。优化编译器获取字节码和类型反馈,并从中生成高度优化的机器码。🚀
JavaScript
是一门动态类型语言,这意味着数据类型可以不停地更改。如果JavaScript
引擎必须每次去检查数据类型对应的值,那将会很慢。为了减少解析代码的时间,优化机器码只处理引擎在运行字节码时见过的情况。如果我们反复使用一段代码,一遍又一遍地返回相同地数据类型,那么可以简单地重复使用经过优化的机器代码以加快处理速度。然而,因为
JavaScript
是动态类型的。同一片段的代码有可能突然就返回了不同类型的数据。如果发生这种情况,机器码会被进行非最佳化,引擎会回退到解析生成的字节码。假设一个特定的函数到目前为止,已经被调用了100次并返回相同的值。那么引擎会认为在第101次,你调用它的时候,它也将返回这个值。
假设我们有下面这个求和函数,到目前为止,我们一直以数字作为参数来调用它:
上图两数和返回的是数值
3
!那么下一次我们调用它,它还会假设我们是通过两个数字类型的数值来调用它。如果上面假设是真的,那么无需进行动态查找了,重复使用经过优化的机器码即可。否则,上面假设不成功的话,它将恢复为原始的字节码,而不是优化的机器码。
比如,我们下次调用
sum
函数,传递的参数其中一个是字符串,而不是数字。因为JavaScript
是动态类型的,所以我们这样做没什么问题。上图代码中,意味着数字
2
将会被强制转换成字符串类型,函数返回字符串12
。引擎已经回到执行解析字节码并更新类型反馈的阶段了。后话
原文:https://dev.to/lydiahallie/javascript-visualized-the-javascript-engine-4cdf
更多内容:https://github.com/reng99
The text was updated successfully, but these errors were encountered: