js在执行代码之前还有两个步骤——>语法分析和预编译,语法分析顾名思义也就是引擎检查你的代码有没有什么低级语法错误,预编译就是在内存中开辟一个空间,存放变量和函数,要值得注意的是预编译发生在函数执行前。
预编译的大致过程如下:
1.函数运行前的一瞬间,一个AO(Active Object)执行期上下文。
2.分析参数,形参作为AO对象的属性名,实参作为AO对象的属性值。
3.分析变量声明,变量名作为属性名,值为undefined,如果遇到同名,不做任何改变。
4.分析函数声明,函数名为属性名,值为函数体,如果遇到同名直接覆盖。
上面是function函数的预编译,与此同时还有对应的全局作用域GO(Global Object),GO没有变量声明和函数声明,预编译过程如下:
1.创建GO对象
2.函数体内所有变量声明整体提升,值为undefined
3.所有函数声明整体提升,值为函数体,如果变量和函数名称相同,那么函数体会覆盖掉变量的值
上面提到了执行期上下文,那么什么是执行期上下文以及作用是什么,执行期上下文也就是:当函数执行的时候,会创建一个执行期上下文的内部对象,存储了定义好的变量,执行期上下文属于独一无二的,每当函数调用一次,就会产生新的执行期上下文,当函数运行完成,执行期上下文就会被销毁。
下面举一些例子来看一看:
a = 100;
function demo(e){
function e(){};
arguments[0] = 2;
console,log(e);
if(a){
var b = 123;
function c(){
}
}
var c;
a = 10;
var a;
console.log(b);
f = 123;
console.log(c);
console,log(a);
}
var a;
demo(1);
console.log(a);
console.log(f);
先分析全局作用域GO
GO={
a : undefined
demo : function
f : undefined
}
GO分析完成开始执行
GO={
a : 100
demo : function
f : 123
}
当函数开始调用的时候,形成AO
demo.AO = {
e : function,
b : undefined,
c : function,
a : undefined,
}
分析完成,开始执行
demo.AO = {
e : 2,
b : undefined,
c : function,
a : 10,
}
所以一次对应的输出为 2 undefined undefined 10 100 123
还有注意区分一下变量声明和函数声明,举个例子,如下
var a = 10 //变量声明
function b(){} //函数声明
var demo = function c(){} //是变量声明而不是函数声明