作用域
作用域分为全局作用域与局部作用域。
全局作用域:单独的js文件或者是直接script标签中的代码都是属于全局作用域的。全局作用域在页面打开的时候创建,页面关闭的时候销毁,全局作用域有一个window对象,所用创建的全局变量都是window的属性保存,函数作为window对象的方法保存。
<script>
//变量 a 直接声明在全局作用域当中,可在控制台直接通过 a 或 window.a进行访问
var a = 100
//函数 fn(){} 创建在全局作用域,预编译后在全局作用域中作为window对象的方法
function fn(){
console.log(a)
}
</script>
局部作用域(函数作用域):在函数内部就是局部作用域,在调用时创建函数作用域,调用结束后函数作用域销毁.
预编译
作用域在代码开始执行之前会有预编译过程.
局部作用域(函数作用域)预编译过程:
- 会创建一个AO对象 (执行上下文)
- 将函数的形参以及创建的变量名,进行提取作为AO对象的属性名赋值为undefined(变量提升)
- 形参实参相统一进行赋值
- 找到函数内部的函数声明,赋予函数体(如果有变量名和函数名相同,则变量会被函数体覆盖)
预编译完成之后,将按照上下顺序对代码进行执行.
预编译过程就是变量提升的过程,变量是声明提升,函数是整体提升.
以下局部作用域(函数作用域的预编译以及执行过程)
<script>
var a = 100
// 执行过程
// 1. 创建AO对象 AO{}
// 2. 形参实参添加到AO对象中作为属性 AO{a:undefined}
// 3. 形参实参统一 AO{a:100}
// 4. 函数赋予函数体 AO{a: function(){}}
// 调用fn(a),将全局变量a作为参数传入fn()
fn(a)
// 代码从上到下执行
function fn(a){
// 输出a ,此时a是函数体function a(){},进行输出
console.log(a)
// 函数a已经预编译过
function a(){
}
// 此时对a进行变量赋值20
a = 20
// a此时为20 ,进行输出
console.log(a)
}
</script>
变量访问规则
定义在全局的变量属于全局变量,在函数内部的变量为局部变量. 变量的访问遵从就近原则.函数内部调用一个变量,会在自身的作用域内进行寻找如果有就直接进行调用, 如果没有会到上一层作用域进行寻找直到全局作用域.如果全局都没有该变量怎会报错. 该变量 is not defined. 作用域的查找机制只能向上找不能向下找
变量声明规则
声明在函数内部的变量属于局部变量,声明在全局的变量属于全局变量.父级作用域不能使用子级的变量.子级作用域可以访问父级作用域的变量.
变量的赋值规则
函数内部给变量赋值,如果内部没有就到上一级作用域进行寻找,如果有就进行赋值操作,没有就继续向上一层进行寻找直到全局作用域.如果还没有就声明为全局变量.