作用域链
在我们实际开发中,通常不止用到一种作用 域。当一个块或者一个函数嵌套在另一个块或者函数中时,就发生了作用域的嵌套。比如这样:
function addA(a) {
console.log(a + b)
console.log(c) // 报错
}
var b = 1
addA(2) //3
我们试图在 addA 这个函数里访问变量 b 的时候,考虑到函数作用域内并没有对 b、c 这两个变量作定义,所以一 开始肯定是找不到的。要想找到 b、c ,该怎么做?就是我们上文提到的“探出头去”,对吧?探出头去,去上层作 用域(全局作用域找),找到了 b ,那么就可以直接拿来用了;没找到 c,并且全局作用域已经没有上层作用域了 (头探不出去了),那就歇菜,报错!这就是上文“执行阶段 ”里我们描述的那个过程。
在这个查找过程中,层层递进的作用域,就形成了一条作用域链。上面这个例子里,作用域链比较短
闭包
function addABC(){
var a = 1,b = 2;
function add(){
return a+b+c;
}
return add;
}
var c = 3
var globalAdd = addABC()
console.log(globalAdd()) // 6
作用域链关系展示如下:
其中 add 这个函数,它嵌套在函数 addABC 的内部,想要查找 a、b、c 三个变量,它得去上层的 addABC 作用域 里找,对吧?像 a、b、c 这样在函数中被使用,但它既不是函数参数、也不是函数的局部变量,而是一个不属 在函数中被使用,但它既不是函数参数、也不是函数的局部变量,而是一个不属 于当前作用域的变量,此时它相对于当前作用域来说,就是一个自由变量 于当前作用域的变量,此时它相对于当前作用域来说,就是一个自由变量。而像 add 这样引用了自由变量的函 引用了自由变量的函 数,就叫闭包。