本文首次发布于 tinypoint`s blog, 作者 @张小点(tinypoint) ,转载请保留原文链接.
前言
作用域链与闭包是javascript的基础也是重点,理解作用域链和闭包是你今后在js中大展拳脚的保证,所以,让我们一起来学习它们吧。

作用域链
执行环境&变量对象
js中每一个函数都有自己的执行环境,而每一个执行环境又都有一个与之关联的变量对象,变量对象里面保存了该环境下定义的所有变量和函数。解析器会在处理数据的时候在后台使用它。
每个函数都有自己的执行环境,当执行流进入到一个函数时,该函数的执行环境就会被推入到一个环境栈中当。当函数执行后,栈会将该执行环境弹出,把控制权返回给之前的执行环境。 <p style="text-align: right">–javascript高级程序设计</p>
var color = 'black';
function fn () {
var color = 'red';
console.log(color);
}
// 在此之上,环境栈中只有全局函数的执行环境
fn(); // fn函数的执行环境进入到环境栈中
//fn函数运行完毕后,他的执行环境从环境栈中弹出,将控制权交还给全局函数的执行环境
作用域链
当代码在一个环境中执行时,会创建变量对象的一个作用域链,在作用域的前端始终是当前代码所在环境的变量对象,如果是函数,就会把他的活动对象作为变量对象。下一个变量对象则是包含环境,在下一个则是下一个包含环境,这样,一直延伸到全局执行环境。
而标识符的解析是沿着作用域链一级一级的搜索标识符的过程,也就是所变量的查找会沿着作用域链一直向上,直到找到为止。
var color = 'black';
function fn () {
console.log(color);
}
fn(); // 'black'
//变量color的查找是沿着fn的活动对象的作用域链进行查找,在自己的
//活动对象中查找发现没有color变量后,会查找全局环境中的color变量
闭包
一般来说,外部环境并不能访问函数内部的变量,因为变量的查找(或者说标识符的解析是沿着作用域链向上的,方向不可逆)
正式如此我们需要引入闭包的概念:闭包是指有权访问另一个函数作用域中变量的函数。
让我们来创建一个闭包
var color = 'black';
function createFn () {
var color = 'blue';
return function () {
console.log(color);
}
}
var fn = createFn();
fn(); //blue
上面的fn函数就是我们说的闭包,原理其实很简单,fn函数的作用域链中,除了自己的变量对象,在上一级就是createFn的变量对象,再上一层才是全局变量对象。所以color是blue而不是black
一般来说,函数运行完该函数的活动对象就会被销毁,而闭包不同,当createFn函数运行完,虽然他的作用域链会被销毁,但是其活动对象被保存在了内存中,一直等到fn被销毁,才会被销毁,因此也就实现访问函数内部变量的功能,但是过度的闭包使用可能导致内存占用过多,请谨慎使用。
好了,今天的总结就此为止了,再见。
参考