JavaScript运行三部曲
脚本执行js引擎都做了什么呢?
- 语法分析
- 预编译
- 解释执行
1.语法分析分析语法是不是错了
2,在语句执行的时候会进行预编译
3.在编译完了进行语句执行
下面就是编译的主要步骤
三。预编译的过程(分四步):
1.(对函数)创建AO对象;(对全局的时候也就是Window)创建GO对象
2.找形参和变量声明,将变量名和形参名作为AO属性名,或GO对象 初始值为undefined
3.将实参值传递形参统一
4.在函数体里面找变量声明,值赋予函数体
在预编译和执行的过程会对赋值语句会对AO,GO中的变量进行覆盖,应该以执行结束后的结果为最终的变量标准。
当出现同命的时候函数为什么会覆盖变量应为函数是第4步变量是第二步就复制了,所以会函数的优先级高
下面是一个例子的全过程:
<script type="text/javascript">
global = 100;
function fn(){
console.log(global); //undefined
global = 200;
console.log(global); //200
var global = 300;
}
fn();
var global;
</script>
1.首先全局对象创建GO执行上下文
GO{
2.对形参和变量声明,将其作为属性名,值为undefined
global:undefined --执行后-->100
3.全局对象没有形参
4.在函数体里找函数声明,值赋予函数体
fn:function fn(){};
}
执行全局
1. global = 100
2.fn();(先预编译fn(),在执行)
(函数预编译产生AO上下文)
AO{
2.对形参和变量声明,将其作为属性名,值为undefined
global:undefined --fn的AO执行到第二句-->200 --fn的AO执行到第四句-->300
3.没形参
4.没函数声明
}
A0执行{
第一句:console.log(global); //undefined在AO的执行上线中global:undefined;
第二句:global = 200;
第三句:console.log(global); //在AO中找global已经变成了200
第四句:global = 300; //
}
所以最后我们的
GO{
global:100
fn:function fn(){};
}
AO{
global:300
}
只有把这个看懂了(看懂一点也没关系)下面我们来写什么是作用域链 ,看完了什么是作用域链
函数也是一个对象在这个对象中有些我们可以访问的属性比如prototype,name,不可以访问的有[[scope]]属性
[[scope]]属性:指的就是我们所说的作用域,其中储存了运行期上下文的集合
作用域链:[[scope]]中储存的执行期上下文对象的集合,这个集合呈链式链接,也叫作用域链
下面看一个例子
function a(){
function b(){
var b = 234;
}
var a= 123;
b();
}
var glob = 100;
a();
在b定义的时候a马上快执行完的时候的图像
首先b会继承了aAO和GO
在b自己执行的时候会变成(图二)
scope chain中的数值代表数值的key,key代表:
0 ---自己的AO(Activation Object)
1---b的AO
2---GO(Clobal Object)
因为这样才会出现说b找不到的变量可以到a中找,但a不到以到b中找都是因为这个(作用域链)的原因
子 - 父 -祖宗--全局 这样一个(作用域链)的过程;