预编译
预编译分为了全局预编译(GO)局部预编译(AO)
1.什么是预编译
预编译又称为预处理,是做些代码文本的替换工作。是整个编译过程的最先做的工作。
局部预编译
局部就是只能在一个地方用,预编译分为4部分
- .创建GO/AO对象
- 找形参和变量声明,将变量和形参名作为AO属性名,值为undefined
- .将实参值和形参统一
- 在函数体里面找函数声明,值赋予函数体
以此为例
1.创建AO对象:我们隐式的在函数中创建了一个AO的对象来盛放函数中的变量,此时对象中并没有值;
2.找形参和变量声明,将变量和形参名作为AO属性名,值为undefined:我们在第二个过程中需按照变量和形参
3.将实参值和形参统一:此时将实参带入函数中由于在函数外 f(1),因此AO中a = 1;
4.在函数体里面找函数声明,值赋予函数体:由于在函数中有 function a() {} ,这一函数因此此时AO中 a =function a (){
c = 10;
};
在之后的运算中,因为预编译把函数提到前面去了,所以打印之后a=11,会把函数给覆盖。
全局预编译和局部预编译是一样的,只不过都可以用来,
GO
结果
最后a的值还是20,因为函数都有一个生命周期,在函数结束是,资源就被释放,函数里面a不是全局变量,所以不会改变外面的全局变量,c在函数里面是全局变量,会被带入全局变量中,不会被释放。所以最后c会被打印出来。
全局函数的生命周期会在页面关闭时结束。
函数生命周期:
- 开始执行前:
创建执行环境栈(数组): 临时保存正在执行的函数的执行环境
向执行环境栈中压入第一个默认函数main()
创建全局作用域对象window
- 定义函数时:
创建函数对象,封装函数定义
声明函数名变量,引用函数对象
函数对象的scope属性引用回创建函数时的作用域
- 调用函数时:
ECS中压入一个新的元素(执行环境)记录新函数的调用
创建一个活动对象,保存本次函数调用用到的局部变量
ECS中的新执行环境元素,引用活动对象
活动对象中的parent属性引用函数的scope指向的父级作用域对象
执行过程中: 优先使用活动对象中的局部变量
局部没有,才延parent向父级作用域找
- 函数调用后:
执行环境栈中本次函数的执行环境出栈
导致活动对象被释放
导致局部变量一同释放
如果里面有多个函数,每一个函数都有一个AO,最里面的一个函数作用域是可以用全部的,他自身的AO,如果没有找到,会找他的父级的AO,一直向上,直到作用域到达GO。