03-静态作用域与动态作用域
7.2 静态作用域与动态作用域
通常,在阅读某段程序源代码的时候,是在看它的语法结构。而一旦程序真正运行起来后,执行逻辑却窜来窜去的。来看一个包含了两个函数的例子:
function f1() {
console.log('one');
}
function f2() {
console.log('two');
}
f2();
f1();
f2();
从语法结构上看,这段程序其实就是一长串语句,通常会自上而下阅读它。然而,当运行这段程序时,执行逻辑就窜来窜去:首先跳到函数 f2 中,然后跳到 f1 (即便它先于 f2 定义),最后又回到 f2 。
在JavaScript中,作用域是静态的,这意味着只通过阅读源代码就能确定变量的作用域。但这不代表作用域总能在源代码中很直观地呈现出来。在本章中,大家将会看到一些例子,这些例子需要细心检查后才能确定其作用域。
静态作用域指的是,在某个作用域内定义了某个函数(而不是调用函数),该作用域包含的所有变量也在该函数的作用域内。看看下面这个例子:
const x = 3;
function f() {
console.log(x); // 会正常运行
console.log(y); // 会导致程序崩溃
}
const y = 3;
f();
不难看出,当方法 f 被定义的时候,变量x就已经存在,但 y 还不存在。紧接着才声明了 y ,然后调用函数 f 。大家会发现当 f 被调用时, x 存在于 f 的作用域中,而y没有。这是个静态作用域的例子:函数 f 可以访问在函数定义时就已经存在的标识符,而不能访问在函数调用时才存在的标识符 。
在JavaScript中,静态作用域适用于全局作用域、块作用域,以及函数作用域。