闭包(Closure)就是一个函数包含着对另一个函数的引用
在创建函数的时候,js 会产生相应的执行环境,在执行环境里会生成活动对象、作用域链等。 执行环境下,js 首先会利用作用域进行变量提升,然后会按顺序进行执行,此时会对变量进行赋值等操作,执行完毕后会把执行环境从执行环境栈中弹出。 但是由于有可能一个函数包含着对另一个活动对象的引用,导致被引用的活动对象一直没有被释放,这就是js 闭包产生的原因。
要理解闭包,首先必须理解Javascript特殊的变量作用域
变量的作用域无非就是两种:全局变量和局部变量
Javascript
语言的特殊之处,就在于函数内部可以直接读取全局变量
var n = 999;
function f1() {
alert(n);
}
f1(); // 999
另一方面,在函数外部自然无法读取函数内部的局部变量
function f1() {
var n = 999;
}
alert(n); // error
这里有一个地方需要注意,函数内部声明变量的时候,一定要使用var命令。如果不用的话,你实际上声明了一个全局变量!
function f1() {
n = 999;
}
f1();
alert(n); // 999
出于种种原因,我们有时候需要得到函数内的局部变量。但是,前面已经说过了,正常情况下,这是办不到的,只有通过变通方法才能实现。
那就是在函数的内部,再定义一个函数。
function f1() {
var n = 999;
function f2() {
alert(n); // 999
}
}
在上面的代码中,函数f2就被包括在函数f1内部,这时f1内部的所有局部变量,对f2都是可见的。但是反过来就不行,f2内部的局部变量,对f1就是不可见的。这就是Javascript
语言特有的"链式作用域"结构(chain scope),子对象会一级一级地向上寻找所有父对象的变量。所以,父对象的所有变量,对子对象都是可见的,反之则不成立。