这是我参与8月更文挑战的第6天,活动详情查看:8月更文挑战
三、词法作用域和动态作用域
- 词法作用域:函数的作用域在
函数定义的时候就决定了 - 动态作用域:函数的作用域在
函数调用的时候才决定的
看如下例子:
let a = 2;
function foo() {
console.log(a); // 会输出2还是3?
}
function bar() {
let a = 3;
foo();
}
bar()
假设 JavaScript 采用词法作用域(也可称为静态作用域),让我们分析下执行过程:
执行 foo 函数,先从 foo 函数内部查找是否有局部变量 a,如果没有,就根据书写的位置,查找上面一层的代码,也就是 a 等于 2,所以结果会打印 2。
假设 JavaScript 采用动态作用域,让我们分析下执行过程:
执行 foo 函数,依然是从 foo 函数内部查找是否有局部变量 a。如果没有,就从调用函数的作用域,也就是 bar 函数内部查找 a 变量,所以结果会打印 3。
前面我们已经说了,JavaScript 采用的是词法作用域,所以这个例子的结果是 2。
词法作用域是写代码的时候就静态确定下来的;而动态作用域并不关心函数和作用域是如何声明以及在何处声明的,只关心它们从何处调用。换句话说,作用域链是基于调用栈的,而不是代码中的作用域嵌套。
Javascript 并不具有动态作用域,它只有词法作用域,简单明了。但是,它的 eval()、with、this 机制某种程度上很像动态作用域,使用上要特别注意。
词法作用域是在写代码或者定义时确定的,而动态作用域是在运行时确定的(this也是!)。词法作用域关注函数在何处声明,而动态作用域关注函数从何处调用。
- this 类似动态作用域
- JavaScript 执行是静态作用域