了解作用域

318 阅读3分钟

什么是作用域

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

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

一言蔽之,“作用域就是一套规则,用于确定在何处以及如何查找变量(标识符) 的规则” 于是:

    var a = 'programmer'

    function foo() {
        var b = 'iceman'

        console.log(a); // programmer
        console.log(b); // iceman
        console.log(c); // c is not defined
    }

    foo()

如上代码,在函数 foo 内,输出了三个变量,那么这三个变量都是从哪来的呢。

而所谓的作用域,在此时就体现出来了,我要在 foo 获取某个 变量(标识符),我要怎么获取指定的变量,怎么获取

我们需要知道的是,作用域分为 函数作用域和全局作用域 (后面还会有块级作用局、模块作用域);

上面的代码中可以这样解读:

a: 输出变量 a => 查找变量 a => 未在 foo 函数作用域中找到 => 去上一级作用域中寻找 => 找到 a => 输出 a => 'programmer'

b: 输出变量 b => 查找变量 b =>foo 函数作用域中找到 b => 输出 b => 'iceman'

c: 输出变量 c => 查找变量 c => 未在 foo 函数作用域中找到 => 去上一级作用域中寻找 => 未找到 c => 搜变全局也未找到变量 c => 抛出错误 => c is not defined

综上所述,这就是 名为 作用域 的查找 规则 我们在查找 a 的时候就已经发现,现在 foo 函数作用域中查找,没有找到,又去上一层作用域中查找,直至找到全局作用域,就好像是顺着一条链条从下往上查找,这条链条,我们就称之为作用域链

暂且知道 作用域 && 作用域链,至于它究竟是什么,以及怎么产生的,我们后续讨论

作用域嵌套

在 ES6 之前, JavaScript 中只存在函数作用域和全局作用域;

全局作用域: 程序代码最大的作用域,只有一个,这个作用域就可以想象成一个海洋,或者 root 函数作用域: 又称局部作用域,局部作用域 顾名思义,小范围的,在程序代码中可存在多个

所谓的作用域嵌套 就体现出来了,全局作用域嵌套局部作用局,而局部作用域里面还可以继续嵌套局部作用域,就像一个洋葱卷

aa

静态作用域 && 动态作用域

词法作用域:函数的作用域在定义 声明的时候就决定了 动态作用域:函数的作用域是在函数调用的时候才决定的

    var value = 1

    function foo() {
        console.log(value);
    }

    function bar() {
        var value = 2
        foo()
    }

    bar() // 输出 1

如上:foo 作用域内没有定义 value 在它所定义的上级作用域里定义了一个 value,在 bar 环境内调用 foo,由于 JavaScript 采用的是词法作用域,也就是在定义时就确定了 作用域,所以 foo 会获取到 它的所定义位置的上一层作用域中的 value 而不是 bar 中的 value

而动态作用域就会与词法作用域相反,采用动态作用域的语言很少,如果是动态作用域,函数的作用域是由调用的时候确定的,就会输出 bar 内的 value