JavaScript 作用域
在 JavaScript 中, 对象和函数同样也是变量。
作用域为变量,对象,函数的集合。
1.1 全局作用域
作用 <script>标签内 / 单个独立js文件的代码环境
变量在函数外声明属于全局作用域。
全局变量:在任意位置都可以访问。
1.2 局部 /(函数)作用域
作用在函数内的代码环境
变量在函数内声明,变量属于局部作用域。
局部变量:只能在函数内部访问。
因为局部变量只作用于函数内,所以不同的函数可以使用相同变量名。
局部变量在函数开始执行时创建,函数执行完后局部变量会自动销毁。
变量的生命周期
开始于变量声明时
全局变量销毁在页面关闭时
局部变量销毁在函数执行后
函数参数
函数参数作用在函数域中故属于局部作用域
作用域链
内层域如果没有所需变量则逐层向上层域查找直至找到后使用;
如果上级域重复包含所需变量则就近域取值;
此过程表现为链。
function a () {
let a = 1
function b () {
// let a = 2
function c () {
// let a = 3
console.log(a)
}
c()
}
b()
}
a()
预解析
JavaScript 代码是由浏览器中的 js 解析器来执行的。
js解析器在运行js代码的时候分为两步:预解析和代码执行预解析会把 变量和函数 的声明放在代码执行之前执行完成。
// 1.变量域解析 将a提前声明初始值为undefind
console.log(n)
var n = 10
/*
2. 函数域解析
function声明的函数可以提升到调用函数前
匿名函数发生的变量提升,不可以提前调用函数
*/
// 函数以声明可以调用
Lookb()
function Lookb () {
console.log('b')
}
// Cannot access 'lookC' before initialization 初始化前无法访问“lookC”
// 在此匿名函数发生的变量预解析,lookC变量被提前声明默认值为undefind,undefind()无法调用函数
lookC()
let lookC = function () {
console.log('C')
}
闭包
<script>
// 闭包将局部变量长期保存,防止污染全局变量
// 下面例子中体现了闭包:通过外层函数作用域保存局部变量a,通过内存函数引用修改外层局部变量a
// 外层函数返回内侧函数aJJson,实现了外层局部变量a的持久化。
// 当不需要此闭包的变量时可以将保存内层函数的变量aJJson 赋值为Null
// 函数执行后a会销毁,所以每次调用都是9
/* function aJJ () {
let a = 10
a--
console.log(a)
} */
function aJJ () {
let a = 10
function aJJson () {
a--
console.log(a)
}
return aJJson
}
let aJJson = aJJ()
// 不需要该闭包则赋值为null
// aJJson = null
</script>