大家好,本文将围绕javascript解码与编码展开说明,javascript源码解析是一个很多人都想弄明白的事情,想搞清楚javascript解析html需要先了解以下几个事情。
JavaScript解析引擎(简称JavaScript引擎),是一个程序,是浏览器引擎的一个部分。
每一个浏览器的JavaScript解析引擎都不相同(因为每个浏览器编写JavaScript解析引擎的语言以及解析原理都不相同)Deepl降重。标准的JavaScript解析引擎会按照ECMAScript文档来实现。虽然每个浏览器的JavaScript解析引擎不同,但是他们最终的结果是相同的。
JavaScript解析引擎根据ECMAScript定义的语言标准来动态执行JavaScript字符串。动态解析JavaScript的过程分两个阶段:语法检查阶段和运行阶段
。
语法检查:包括词法分析、语法分析。
运行阶段:包括预解析、执行阶段。
在JavaScript引擎解析JavaScript代码的过程,如果遇到错误就会立即跳出当前的代码块,不会继续执行下面的代码,直接执行下一个代码块。
核心:词法分析是将字符流(char stream)转换为记号流 (token stream)。
JavaScript引擎会将我们写的代码当成字符串分解成词法单元(token)。例如,var a = 2
,这段程序会被分解成:“var、a、=、2、;
” 五个token
。每个词法单元token
不可再分割。可以试试这个网站地址查看 token
将词法分析阶段产生的token
, 转换成树状结构的 “抽象语法树(AST)
”
当语法检查正确无误之后,就可以进入运行阶段。
全局代码处理过程:
函数处理过程:
JavaScript代码执行时,都会在执行上下文环境中进行。
JavaScript
执行上下文有三种:
全局执行上下文
当JS引擎执行全局代码的时候,会编译全局的代码并创建全局执行上下文,它会做两件事:1、创建一个全局对象(window
)。2、将this
指向该全局对象;全局上下文在整个页面声明周期有效,并且只要一个。
函数执行上下文
当调用一个函数的时候,函数体内的代码会被编译,并创建函数执行上下文,一个般情况下,函数执行结束之后,该函数执行上下文就会销毁。
eval执行上下文
调用eval
函数也会创建自己的执行上下文(eval函数容易导致恶意攻击,并且运行代码的速度比相应的替代方法慢,因此不推荐使用)
用来存储代码运行时创建的所有执行上下文
当JS引擎开始执行第一行代码时,它会创建一个全局执行上下文并且将它压入执行栈中,每当引擎遇到一个函数调用时,首先会创建该函数的执行上下文,并且将其压入执行栈中。当函数执行结束时,执行上下文就会从执行栈中弹出。
执行上下文的创建分两个阶段:
创建阶段
执行上下文在创建阶段会做三件事:
this
绑定this
在全局执行上下文中,this
的指向时全局对象(window)。
值函数执行上下文中,this
的指向取决于该函数是谁调用的。
词法环境
词法环境是一种规范类型,基于ECMAScript代码的词法嵌套结构来定义标识符和具体变量和函数的关联。
简单来说词法环境
是一种持有标识符——变量
映射的结构(这里的标识符
指的是变量/函数的名字,而变量
是原始数据或对象的引用)。
在词法环境
的内部一般含有两个组件:环境记录器
、外部环境的引用
因为区分全局执行上下文
和函数执行上下文
,所有词法环境
也有两种类型:
null
。在环境记录器(对象环境记录器)
中,包含用户定义的全局变量,函数等,并且this
指向全局对象全局环境
或 函数环境
,环境记录器(声明式环境记录器)
中存储函数内部定义的变量、方法、还有一个arguments
对象和传递给函数的参数length
变量环境
变量环境也是一个词法环境,所有它有着词法环境定义的所有属性。在ES6中,词法环境和变量环境的一个不同之处就是前者存储函数声明和变量(let
和const
),而后者值存储var
声明的变量和函数。
JavaScript代码
let a = 20;
const b = 30;
var c;
function multiply(e, f) {
var g = 20;
return e * f * g;
}
c = multiply(20, 30);
执行上下文
//全局执行上下文
GlobalExectionContext = {
ThisBinding: ,
//变量环境
LexicalEnvironment: {
EnvironmentRecord: {
Type: "Object",
//存储 let/const 变量绑定
a: < uninitialized >,
b: < uninitialized >,
multiply: < func >
}
//外部环境的引用
outer:
},
// 词法环境
VariableEnvironment: {
EnvironmentRecord: {
Type: "Object",
//存储并直接定义 var 变量
c: undefined,
}
outer:
}
}
//函数执行上下文
FunctionExectionContext = {
ThisBinding: ,
//词法环境
LexicalEnvironment: {
EnvironmentRecord: {
Type: "Declarative",
// 词法环境生成的arguments属性
Arguments: {0: 20, 1: 30, length: 2},
},
//外部引用指向全局环境
outer:
},
// 变量环境
VariableEnvironment: {
EnvironmentRecord: {
Type: "Declarative",
//存储并直接定义 var 变量
g: undefined
},
outer:
}
}
注意 let
和 const
定义的变量没有值,但 var
定义的变量被设成了 undefined
。
执行阶段
这是整篇文章中最简单的部分。在此阶段,完成对所有变量的分配,最后执行代码.
注意 在执行阶段,如果 JavaScript 引擎不能在源码中声明的实际位置找到let
变量的值,它会被赋值为 undefined