作用域介绍
- 作用域:变量可以使用的范围
- 作用域分为全局作用域和局部作用域
- 全局作用域
- 页面打开就是一个全局作用域
- 生命周期:页面打开到页面关闭
- 局部作用域(私有作用域)
- 在js中只有函数的
{}
才可以决定一个局部作用域 - 生命周期:函数调用到函数执行完毕
- 作用域的上下级别关系(父子关系)
- 在A作用域中定义了函数B,则函数B局部作用域的父级(上一级)作用域就是A作用域
function fn() {
function ff() {
}
}
变量的三种行为
- 变量有且仅有三种行为:定义、访问、赋值
- 变量定义行为:创建变量(声明定义变量)
var
声明变量- 声明式定义函数(定义函数名变量)
- 函数内的形参变量
- 隐式全局变量(不推荐使用)
- 变量访问行为:需要使用到变量中的值
- 变量输出
- 变量参与运算
- 变量赋值
- 函数调用(函数名变量的访问)
- 变量作为实参
- 变量赋值行为:将数据存储到变量中
- 给变量赋值操作
- 实参给形参变量赋值
- 注意:函数名、形参也是变量
作用域变量的定义机制
- 在哪个作用域中定义的变量,该变量就只能在该作用域及其后代作用域中使用
- 在全局中定义的变量,称为全局变量
- 在局部作用域中定义的变量,称为局部变量(私有变量)
- 局部变量只能在定义变量的局部作用域及其后代作用域中使用
var n = 100
function fn() {
console.log('fn --> n', n)
var m = 999
function ff() {
console.log('ff --> m', m)
}
ff()
}
console.log('全局n', n)
fn()
console.log('全局m', m)
作用域变量的访问机制
- 访问变量的时候(需要使用变量值),会先去查找变量的定义
- 先在当前作用域中查找变量(变量定义),找到则使用,并停止查找
- 如果找不到,则往上一级作用域中查找,找到则使用,并停止查找
- 如果还是找不到,则继续逐级往上一级作用域中查找,找到则使用,并停止查找
- 如果逐级往上一级作用域查找,一直找到全局作用域还是没找到该变量,则报错
var n = 100
function fn(x) {
console.log(n)
f1();
function f1() {
console.log(x)
}
}
function ff() {
console.log(x)
}
fn(200)
ff()
作用域变量的赋值机制
- 给变量赋值的时候,会先去查找变量的定义
- 先在当前作用域中查找变量(变量定义),找到则给该作用域的变量赋值,并停止查找
- 如果找不到,则去上一级作用域中查找,找到则给该作用域的变量赋值,并停止查找
- 如果还是找不到,则继续往上一级作用域中查找,找到则给该作用域的变量赋值,并停止查找
- 如果一直找到全局作用域还是没找到该变量,则会将该变量定义为全局变量并赋值
- 此方式定义的全局变量称为隐式全局变量
- 注意:强烈不建议定义隐式全局变量(严格模式下会报错)
var n = 100
function fn() {
n = 200
}
console.log(n)
fn()
console.log(n)
作用域链
- 当变量访问或赋值的时候,需要查找该变量
- 变量的查找过程中,从当前作用域逐级往上一直链接到全局作用域所形成的链状结构称为作用域链
- 作用:为了让程序中变量的使用(访问和赋值)都是有序的