理解JS中的作用域链

前言

       承接之前的关于执行环境的理解,这次主要来来讲解一下JS中的作用域链和词法环境,为什么还要讲词法环境呢,因为我觉得如果单独讲作用域链不容易讲清楚,必须要先理解词法环境才能比较好理解作用域链。

在讲这两个概念之前想来看一个简单的例子:

1
2
3
4
5
6
7
8
9
10
11
function foo() {
console.log(a);
}

function bar() {
var a = 3;
foo();
}

var a = 2;
bar();

结果是什么大家可以自己先思考一下,等讲完词法环境与作用域链再来详细说说结果以及为什么会是这样的结果。

词法环境

词法环境(Lexical Environments):词法环境(Lexical Environments)是一种规范类型,用于根据ECMAScript代码的词法嵌套结构来定义标识符与特定变量和函数的关联。

以上是官方对于词法环境的一段解释,可能看起来不是很好理解,但是这其中想表达的意思就是:词法环境是一种规则,这种规则规定了如何来寻找某个变量或者标示符,而这个规则最终规定在寻找某个变量或者标示符的时候是根据代码结构来决定的,这也就意味着词法环境在书写代码的时候就已经确定了。

可能我这样的解释也不是特别好理解,后面还会结合前面的例子来讲。

关于词法环境更详细的知识我这里就不解释了,只要知道以上关于词法环境的概念就好理解作用域链了。

作用域链

作用域链:作用域链,是由当前环境与上层环境的一系列变量对象组成,它保证了当前执行环境对符合访问权限的变量和函数的有序访问。

理解作用域链重点是理解两个关键词,一个是上层环境,一个是变量对象

作用域链也很好理解,就是一条单线的链子,用来寻找变量用的。

当当前环境找不到相应变量或者标识符时,就会顺着作用域链向上层环境来寻找相应的变量或者是标识符。

可以通过一个简单的例子来理解:

1
2
3
4
5
6
7
8
var a = 100;
function foo() {
bar();
function bar() {
console.log(a);
}
}
foo();//结果100

当 bar 函数输出 a 时就会顺着作用域链向外面找,而此时 bar 函数执行环境中保存的 作用域链 可以表示为:
AO(bar)–>AO(foo)–>VO(global)

作用域链的最前端一定是当前自己执行环境中的变量对象,末尾一定是全局变量对象。因为函数开始执行之后变量对象转化为活动对象,所以这里用AO来表示。

例子分析

相信到这里已经对作用域链比较的理解了,那么我们现在再回过头来看一开始的那个例子:

1
2
3
4
5
6
7
8
9
10
11
function foo() {
console.log(a);
}

function bar() {
var a = 3;
foo();
}

var a = 2;
bar();

最终的答案是 2

不知道各位有没有想到是这个结果,如果没有想到也正常,那我们一步一步来分析一下为什么会是这个结果:

  1. 首先在全局环境中调用了 bar 这个函数,此时就会创建 bar 这个函数的执行环境,并且创建相应的 变量对象 此时这个函数的变量对象中就会保存有 a 这个变量,并且当开始执行函数的时候就会转化为活动对象,并且 a 这个变量可以访问,且值为 3。

  2. 接着开始调用 foo 函数,那么这里就要注意很重要的一点了, foo 这个函数会被保存在哪个环境当中,是 bar 函数还是全局函数当中?这里就要用到前面提到的词法环境了,前面有提到词法环境是一个规则并且规定寻找某个变量或者标示符的时候是根据代码结构来决定的,也就是说不管 foo 函数是在哪里被调用的,它始终都是 全局环境中创建的,这一点在代码写好时就已经确定了,这大致就是词法环境的意思。

  3. 并且当全局执行环境创建时也会 找到所有的函数声明,所以会将 foo 函数保存进全局的变量对象当中。

  4. 当开始执行 foo 函数的时候因为当前环境的变量对象当中并没有 a 这个变量,所以会通过作用域链来找,我们回顾作用域链的概念:是由当前环境与上层环境的一系列变量对象组成, 所以就会沿着作用域链向上层环境寻找 a 这个变量,那么此时我们就很清楚 foo 函数的上层环境是谁了,是全局环境,所以这个过程大致可以这样表示:
    AO(foo)–>VO(global)

  5. 最终找到全局环境变量对象中的 a 为2,所以最后结果为2。

总结

相信通过这几个例子大家已经对词法环境和作用域链有一个比较清楚的认识,也对JS的运作机制有了更加清楚的认识。

这些也都是我个人浅显的理解,如有错误欢迎指出。

参考

作用域与作用域链
彻底搞懂javascript-词法环境(Lexical Environments)

-------------本文结束感谢您的阅读-------------