JavaScript 系列之作用域(二)

159 阅读2分钟

这是我参与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也是!)。词法作用域关注函数在何处声明,而动态作用域关注函数从何处调用。

  1. this 类似动态作用域
  2. JavaScript 执行是静态作用域