作用域链

在我们实际开发中,通常不止用到一种作用 域。当一个块或者一个函数嵌套在另一个块或者函数中时,就发生了作用域的嵌套。比如这样:

  1. function addA(a) {
  2. console.log(a + b)
  3. console.log(c) // 报错
  4. }
  5. var b = 1
  6. addA(2) //3

2021-06-19_132608.png

我们试图在 addA 这个函数里访问变量 b 的时候,考虑到函数作用域内并没有对 b、c 这两个变量作定义,所以一 开始肯定是找不到的。要想找到 b、c ,该怎么做?就是我们上文提到的“探出头去”,对吧?探出头去,去上层作 用域(全局作用域找),找到了 b ,那么就可以直接拿来用了;没找到 c,并且全局作用域已经没有上层作用域了 (头探不出去了),那就歇菜,报错!这就是上文“执行阶段 ”里我们描述的那个过程。
在这个查找过程中,层层递进的作用域,就形成了一条作用域链。上面这个例子里,作用域链比较短

2021-06-19_132733.png

闭包

  1. function addABC(){
  2. var a = 1,b = 2;
  3. function add(){
  4. return a+b+c;
  5. }
  6. return add;
  7. }
  8. var c = 3
  9. var globalAdd = addABC()
  10. console.log(globalAdd()) // 6

2021-06-19_133413.png

作用域链关系展示如下:
2021-06-19_133809.png

其中 add 这个函数,它嵌套在函数 addABC 的内部,想要查找 a、b、c 三个变量,它得去上层的 addABC 作用域 里找,对吧?像 a、b、c 这样在函数中被使用,但它既不是函数参数、也不是函数的局部变量,而是一个不属 在函数中被使用,但它既不是函数参数、也不是函数的局部变量,而是一个不属 于当前作用域的变量,此时它相对于当前作用域来说,就是一个自由变量 于当前作用域的变量,此时它相对于当前作用域来说,就是一个自由变量。而像 add 这样引用了自由变量的函 引用了自由变量的函 数,就叫闭包。