js作用域和预编译
简单理解:一般理解为变量的作用范围
-
全局作用域
- 全局作用域在页面打开时被创建,页面关闭时被销毁
- 编写在script标签中的的变量和函数,在页面任意位置都可以访问到,此时作为全局作用域
- 全局作用域中有全局对象window,代表浏览器窗口,由浏览器创建
- 全局作用域中声明的变量和函数做为window对象的属性和方法保存
-
函数作用域
- 当调用函数时,函数作用域被创建,函数执行完毕,函数作用域被销毁
- 每调用一次函数,都会创建一个新的函数作用域,他们之间是独立的
- 在函数作用域中可以访问到全局作用域的变量,在函数外部是无法访问函数作用域内部变量的
- 在函数内部访问变量时,先从函数本身的作用域中找,找到就直接用,找不到就会在函数上一级作用域中寻找,一直找到全局
详细理解:
执行期的上下文:
- 函数代码执行前期,会创建一个执行上下文的内部对象AO(函数作用域)
- 这个内部的对象是预编译时创建出来的,因为函数被调用时,会先进行预编译
- 在全局执行代码行的前期会创建一个执行期的上下文对象GO(全局作用域)
函数预编译的过程:
- 创建AO对象
- 找形参和变量声明,将形参和变量名作为AO对象的属性名,值初始为undefined
- 实参形参统一
- 在函数体里找函数声明,值赋予函数体
例题(案例是从前端斌哥视频看的,解释的很详细):
function fn(a, c){
console.log(a)
var a = 123
console.log(a)
console.log(c)
function a(){}
if(false){
var d = 678
}
console.log(d)
console.log(b)
var b = function(){}
console.log(b)
function c(){}
console.log(c)
}
fn(1, 2)
过程:
AO: {
a: undefined
c: undefined
d: undefined
b: undefined
}
AO: {
// 3.实参形参统一
a: 1
c: 2
d: undefined
b: undefined
}
AO: {
// 4.在函数体里找函数声明,值赋予函数体,注意的是函数声明和函数表达式赋值不是一回事
a: function a(){};
c: function c(){};
d: undefined
b: undefined
}
此时预编译完成,AO作用域已形成,可以进行下一步的代码执行。
function fn(a, c){
console.log(a);
var a = 123;
console.log(a);
console.log(c);
function a(){};
if(false){
var d = 678
};
console.log(d);
console.log(b);
var b = function(){};
console.log(b);
function c(){};
console.log(c);
};
fn(1, 2)