# 作用域
作用域(scope)是变量与函数在程序中的可见性范围。作用域控制着当前执行代码对变量与函数的访问权限。 作用域有两种常见的模型,一种叫做词法作用域(Lexical Scope), 一种叫做动态作用域(Dynamic Scope)。JavaScript 采用的是词法作用域,也是静态作用域。
# 词法作用域
词法作用域是在书写代码或者定义时确定的,而动态作用域是在运行是确定的,前者关注函数在何处声明,而动态作用域关注函数从何处调用。
举个例子说明:
var a = 1;
function foo() {
console.log(a)
}
function bar() {
var a = 2;
foo()
}
bar()
2
3
4
5
6
7
8
9
10
11
12
因为 Javascript 是采用词法作用域,所以 bar 函数执行后 foo 函数执行,foo 函数从内部查找是否有局部变量 a, 如果没有,就根据书写的位置,查找上面一层的代码, 也就是 a = 1, 所以结果打印1。
# 作用域类型
作用域有全局作用域、函数作用域以及ES6之后的块级作用域。
# 全局作用域
在代码中任何地方都能访问到的对象拥有全局作用域。一般情况以下几种情况拥有全局作用域。
- 最外层函数
- 所有未定义直接赋值的变量自动声明为全局变量,拥有全局作用域
- window对象
# 函数作用域
是指声明在函数内部的变量,只在当前函数内部可以访问。内部嵌套的作用域会进行分层,内层作用域可以访问外层作用域的变量,反之则不行
作用域访问:③ -> ② -> ①, 不可逆。
可以理解作用域访问过程是,在一个建筑里面有一部只能升不能降的电梯,只能向上查找直到全局作用域。
# 块级作用域
块级作用域可以通过 let 和 const 声明,声明的变量在指定块的作用域外无法被访问。花括号{}
中间内的块语句也是是块级作用域。
# 动态作用域
动态作用域中,变量的值与定义无关,由运行是决定。 bash 就是动态作用域,可以尝试将下面代码保存为 scope.bash 文件,用命令 bash ./scope.bash 运行,看看打印的值是多少
a=1
function foo() {
echo $a;
}
function bar() {
local a=2;
foo;
}
bar
2
3
4
5
6
7
8
9
最终的结果是2。
# 参考
1、从上下文,到作用域
2、JavaScript深入之词法作用域和动态作用域
3、深入理解JavaScript作用域和作用域链