作用域可以理解为一个存放变量的独立空间。它们之间可嵌套,作用域之间会形成引用关系,这条链叫做作用域链。
# 作用域
什么是作用域呢?
简单理解就是变量作用的范围。作用域让变量不会外泄、暴露出去,提高程序的可靠性,减少命名冲突。作用域之间是可以嵌套的,内层作用域可以访问外层作用域的变量,反之则不行。
# 作用域分类
JS 目前的作用域可分为三种:全局作用域、函数作用域、块级作用域。
# 全局作用域
在代码中任何地方都能访问的变量拥有全局作用域,当程序运行时全局作用域被创建,程序销毁时全局作用域被销毁。
- 在最外层定义的函数和变量拥有全局作用域
<script>
const name = 'f'
function fn() {}
</script>
- window对象的属性拥有全局作用域
function fn() {
window.age = 18
}
fn()
console.log(age) // 依然能访问到 name 值,注意:要想访问到 age 这个值,函数必须先执行
- 非严格模式下,未声明的直接使用的变量拥有全局作用域
function fn() {
a = 1
}
fn()
console.log(a) // 可以访问到 a
# 函数作用域
在函数内部声明的变量具有函数作用域,这个变量只在函数内部起作用,函数执行完毕后,对应的函数作用域销毁。
function fn() {
var a = 1
console.log(a) // 1
}
fn()
console.log(a) // a is not defined
# 块级作用域
ES6 前没有块级作用域,ES6 后,在 {} 中使用 let、const 声明的变量拥有块级作用域,所声明的变量在块作用外无法访问。
{
const a = 1
let b = 1
console.log(a) // 1
console.log(b) // 1
}
console.log(a) // a is not defined
console.log(b) // b is not defined
# 作用链
作用域是可以嵌套的,当访问一个变量的时候,会先在当前作用域中查找,如果找不到就在它外层的作用域查找,直到查找到全局作用域中,如果中间找到这个变量就原路返回,否则报错,查找的这个链就是作用域链。
执行上下文在运行时确定,函数作用域在定义时确定。
参考: