深入 JS 之作用域

117 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第2天,点击查看活动详情

在深入 JS 的执行原理之前,我们先要了解一个关键的概念, 那就是 作用域, 我们要知道 JS 的作用域是如何决定的.

作用域

作用域是指程序源代码中定义变量的区域

作用域规定了如何查找变量,也就是当前执行代码对于变量的访问权限

作用域分为:

  • 静态作用域
  • 动态作用域

从名字的语义我们能看出他们区别, 这是语义上的区别, 在程序中,他们分别代表什么呢?

静态作用域: 函数的作用域在函数定义的时候就决定了.

动态作用域: 函数的作用域是调用的时候才决定的.

具体什么意思呢? 接下来看看

静态作用域

什么是静态作用域呢, 我们一起来看这个例子

var value = 1;
​
function foo() {
    console.log(value);
}
​
function bar() {
    var value = 2;
    foo();
}
​
bar();

JS 中,我们都知道,这段代码是会输出 1, JS 是如何查找变量的呢?来分析下执行流程

在函数 foo 执行的时候, 使用了 value 变量,现在函数内部查找, 如果没有, 则向 函数声明时 的外层进行查找, 于是找到了全局声明的 value 变量, 取到值并进行打印输出.

JS 的这种查找就是 静态作用域, 也叫做 词法作用域

静态作用域的规则就是, 在函数声明的时候, 它能访问的变量,就已经决定了, 不会随着调用位置的不同而变化.

动态作用域

与静态作用域相对的就是动态作用域, 同样的例子

var value = 1;
​
function foo() {
    console.log(value);
}
​
function bar() {
    var value = 2;
    foo();
}
​
bar();

如果是动态作用域, 在这个例子中则会输出 2, 它的执行流程是这样的

执行 foo 函数, 然后从 foo 函数内部查找是否有局部变量 value. 如果没有, 就从调用函数的作用域, 也就是 bar 函数内部查找 value 变量, 所以结果会打印 2.

什么语言是 动态作用域 呢?

其实我们的 bash 就是动态作用域的, 我们可以复制以下代码, 到 terminal 中.

value=1
function foo () {
    echo $value;
}
function bar () {
    local value=2;
    foo;
}
bar

我们来看看这个结果

bash.png