作用域
1、作用域的深刻理解
执行期的上下文 当函数代码执行的前期,会创建一个执行器上下文的内部对象 AO (AO为真正的作用域)
这个内部的对象是预编译的时候创建的,因为当函数被调用的时候,会先进行预编译
在全局代码执行的前期会创建一个执行器的上下文的对象GO
2、作用域的浅理解
全局作用域
1、全局作用域在页面打开时被创建,页面关闭时被销毁
2、script 标签中的变量和函数,作用域为全局,在页面任何位置可以访问到
3、在全局作用域中有全局对象window,代表一个浏览器窗口,由浏览器创建,可以直接调用
4、全局作用域中声明的变量和函数会作为window对象的属性和方法保存
全局作用域预编译
1、创建 GO 对象
2、找变量声明,将变量名作为 GO 对象的属性名,值为undefined
3、找函数声明,值赋予函数体
函数作用域
1、调用函数时,函数作用域被创建,函数执行完毕,函数作用域被销毁
2、每调用一次函数就会创建一个新的函数作用域,他们之间是互相对立的
3、函数作用域中可以访问当全局作用域的变量,在函数外无法访问到函数作用域内的变量
4、在函数作用域中访问变量、函数时,会先在自身作用域中寻找,若没有找到,则会在函数的上一级作用域中寻找,直到全局作用域
函数作用域预编译
1、创建 AO 对象
2、找形参和变量声明,将变量和形参名,当作 AO 对象的属性名,值为 undefined
3、实参形参统一
4、在函数体内找函数声明,值赋予函数体
备注:创建的预编译对象,全局叫 GO ,函数内部的叫 AO
// 预编译 示例
function fn(a,c) {
console.log(a); // function a () {}
var a = 123;
console.log(a); // 123
console.log(c); // function c () {}
function a () {}; // (此为函数声明)
if(false) {
var d = 678;
}
console.log(d); // undefined
console.log(b); // undefined
var b = function () {}; // (此为函数的表达式,不是函数的声明)
console.log(b); // function () {}
function c () {}; // (此为函数声明)
console.log(c); // function c () {}
}
fn(1,2)
// 解析 预编译
1、创建 AO 对象
2、找形参和变量声明,将变量和形参名,当作 AO 对象的属性名,值为 undefined (不用考虑是否能进入判断条件)
3、实参形参统一
4、在函数体内找函数声明,值赋予函数体
AO {
// 变量声明 : 值 : 参数统一 :值赋予函数体
a : undefined : 1 : function a () {}
c : undefined : 2 : function c () {}
d : undefined
b : undefined
}
3、实参形参统一
作用域链
会被保存到一个隐式的属性中,[[scope]] 这个属性是我们用户访问不到的,但确实存在的,让 js 引擎来访问,里面存储的就是作用域链 AO、GO、AO 和 GO集合
// 作用域链 示例
var global
function a () {
// a 执行 b才定义
function b () {
// 首先 b 函数的 AO,a 函数的 AO,最后是全局的 GO
var bb = 123;
aa = 0;
}
var aa = 123
b()
}
a()