预编译
js运行三部曲
- 语法分析
- 预编译
- 解释执行
-
函数声明整体提升
test() function test(){ console.log('aa') } // 控制台输出:aa -
变量 声明提升
console.log(a) var a = 'aa' // 控制台输出:undefined
预编译前奏
-
imply global 暗示全局变量:即任何变量,如果变量未经声明就赋值,此变量就为全局对象所有。
a = 123; var a = b = 123 -
一切声明的全局变量,全是window的属性
var a = 123;==> window.a = 123 console.log(a); === console.log(window.a)
函数预编译四部曲
- 创建AO对象(Activation Object,也称 执行期上下文 或 作用域)
- 找形参和变量声明,将变量和形参名作为AO属性名,值为undefined
- 将实参值和形参统一
- 在函数体里面找函数声明,值赋予函数体
预编译发生在函数执行的前一刻
function fn(){
console.log(a)
var a = 123
console.log(a)
function a(){}
console.log(a)
var b = function(){}
console.log(b)
function c(){}
}
fn(1)
// 以上函数输出为:
> [Function: a]
> 123
> 123
> [Function: b]
执行过程解析
-
创建AO(执行期上下文)
AO {} -
执行步骤2,形参和变量重复只留一个 var a 和 var b
AO { a:undefined b:undefined } -
执行步骤3
AO { a:1 b:undefined } -
执行步骤4,只有a 和 c是函数声明
AO { a:function a(){} b:undefined c:function c(){} }AO对象创建完成
-
开始执行函数
AO { a:123 b:function(){} c:function c(){} }
全局预编译三部曲
和函数预编译一样,少了第三步
创建GO对象(Global Object)
GO === Window 对象
作用域
- [[scope]]:每个JavaScript函数都是一个对象,对象中有些属性我们可以访问,但有些不可以,这些属性仅供JavaScript引擎存取,[[scope]] 指的就是我们所说的作用域,其中存储了运行期上下文的集合。
- 作用域链:[[scope]] 中所存储的执行期上下文对象的集合,这个集合呈链式链接,我们把这种链式链接叫做作用域链。
- 运行期上下文:当函数执行时,会创建一个称为**执行期上下文(AO)**的内部对象,一个执行期上下文定义了一个函数执行时的环境,函数每次执行时对应的执行上下文都是独一无二的,所以多次调用一个函数会导致创建多个执行上下文,当函数执行完毕,它所产生的执行上下文被销毁。
- 查找变量:从作用域链的顶端依次向下查找。
function a(){
function b(){
var b = 234;
}
var a = 123;
b();
}
var glob = 100;
a();