2014-05-21 18:42:46| 分类: Javascript | 标签: |举报 |字号大中小 订阅
了解 JS 引擎的工作方式,所以下面我们就把 JS 引擎对一个方法的解析过程进行一个稍微深入一些的介绍
解析过程
1、执行顺序
编译型语言,编译步骤分为:词法分析、语法分析、语义检查、代码优化和字节生成。 解释型语言,通过词法分析和语法分析得到语法分析树后,就可以开始解释执行了。这里是一个简单原始的关于解析过程的原理,仅作为参考,详细的解析过程(各种JS引擎还有不同)还需要更深一步的研究JavaScript执行过程,如果一个文档流中包含多个script代码段(用script标签分隔的js代码或引入的js文件),它们的运行顺序是:
步骤1. 读入第一个代码段(js执行引擎并非一行一行地执行程序,而是一段一段地分析执行的)2、特殊说明
全局域(window)域下所有JS代码可以被看成是一个“匿名方法“,它会被自动执行,而此“匿名方法“内的其它方法则是在被显示调用的时候才被执行
3、关键步骤
上面的过程,我们主要是分成两个阶段
4、关键概念
到这里,我们再更强调以下一些概念,这些概念都会在下面用一个一个的实体来表示,便于大家理解
语法分析树(SyntaxTree)可以直观地表示出这段代码的相关信息,具体的实现就是JS引擎创建了一些表,用来记录每个方法内的变量集(variables),方法集(functions)和作用域(scope)等。执行环境(ExecutionContext)可理解为一个记录当前执行的方法【外部描述信息】的对象, 记录所执行方法的类型,名称,参数和活动对象(activeObject) 活动对象(activeObject)可理解为一个记录当前执行的方法【内部执行信息】的对象,记录内部变量集(variables)、内嵌函数集(functions)、实参(arguments)、作用域链(scopeChain)等执行所需信息,其中内部变量集(variables)、内嵌函数集(functions)是直接从第一步建立的语法分析树复制过来的 词法作用域:变量的作用域是在定义时决定而不是执行时决定,也就是说词法作用域取决于源码,通过静态分析就能确定,因此词法作用域也叫做静态作用域。 with和eval除外,所以只能说JS的作用域机制非常接近词法作用域(Lexical scope) 作用域链:词法作用域的实现机制就是作用域链(scopeChain)。作用域链是一套按名称查找(Name Lookup)的机制,首先在当前执行环境的 ActiveObject 中寻找,没找到,则顺着作用域链到父 ActiveObject 中寻找,一直找到全局调用对象(Global Object)
5、实体表示
2. 建立分析树/*全局(window)域下的一段代码*/
var i = 1,j = 2,k = 3;
function a(o,p,x,q){
var x = 4;
alert(i);
// 在函数a中定义新的函数b,并且有变量i,y
function b(r,s) {
var i = 11,y = 5;
alert(i);
//在函数b中定义新的函数c,并且有变量z
function c(t){
var z = 6;
alert(i);
};
//在b中定义 函数表达式 d
var d = function(){
alert(y);
};
c(60);
d();
};
b(40,50);
}
a(10,20,30);
上面就是关于语法分析树的一个简单表示,正如我们前面分析的,语法分析树主要记录了每个 function 中的变量集(variables),方法集(functions)和作用域(scope)。/**
* 模拟建立一棵语法分析树,存储function内的变量和方法
*/
var SyntaxTree = {
// 全局对象在语法分析树中的表示
window: {
variables:{
i:{ value:1},
j:{ value:2},
k:{ value:3}
},
functions:{
a: this.a
}
},
a:{
variables:{
x:'undefined'
},
functions:{
b: this.b
},
scope: this.window
},
b:{
variables:{
y:'undefined'
},
functions:{
c: this.c,
d: this.d
},
scope: this.a
},
c:{
variables:{
z:'undefined'
},
functions:{},
scope: this.b
},
d:{
variables:{},
functions:{},
scope: {
myname:d,
scope: this.b
}
}
};
上面每一个方法的执行环境都存储了相应方法的类型(function)、方法名称(funcName)、活动对象(ActiveObject)、作用域链(scopeChain)等信息,其关键点如下:/**
* 执行环境:函数执行时创建的执行环境
*/
var ExecutionContext = {
window: {
type: 'global',
name: 'global',
body: ActiveObject.window
},
a:{
type: 'function',
name: 'a',
body: ActiveObject.a,
scopeChain: this.window.body
},
b:{
type: 'function',
name: 'b',
body: ActiveObject.b,
scopeChain: this.a.body
},
c:{
type: 'function',
name: 'c',
body: ActiveObject.c,
scopeChain: this.b.body
},
d:{
type: 'function',
name: 'd',
body: ActiveObject.d,
scopeChain: this.b.body
}
}
上面每一个活动对象都存储了相应方法的内部变量集(variables)、内嵌函数集(functions)、形参(parameters)、实参(arguments)等执行所需信息,活动对象关键点/**
* 活动对象:函数执行时创建的活动对象列表
*/
var ActiveObject = {
window: {
variables:{
i: { value:1},
j: { value:2},
k: { value:3}
},
functions:{
a: this.a
}
},
a:{
variables:{
x: {value:4}
},
functions:{
b: SyntaxTree.b
},
parameters:{
o: {value: 10},
p: {value: 20},
x: this.variables.x,
q: 'undefined'
},
arguments:[this.parameters.o,this.parameters.p,this.parameters.x]
},
b:{
variables:{
y:{ value:5}
},
functions:{
c: SyntaxTree.c,
d: SyntaxTree.d
},
parameters:{
r:{value:40},
s:{value:50}
},
arguments:[this.parameters.r,this.parameters.s]
},
c:{
variables:{
z:{ value:6}
},
functions:{},
parameters:{
u:{value:70}
},
arguments:[this.parameters.u]
},
d:{
variables:{},
functions:{},
parameters:{},
arguments:[]
}
}
评论