Javascript 的函数式对象(二)从垃圾回收器的角度理解闭包
function outerFunc(){
var privateAttr = 10;
return function(){
privateAttr *= 2;
return privateAttr;
};
}
// 通过调用outerFunc函数,返回一个指向innerFunc函数的引用,
// 这个引用被赋给变量refInnerFunc
var refInnerFunc = outerFunc();
alert(refInnerFunc());
// 通过 refInnerFunc 这个引用调用到 innerFunc 函数
refInnerFunc(); // return 20 变量privateAttr可被innerFunc访问并修改
refInnerFunc(); // return 40
// 调用outerFunc函数,创建了一个新的innerFunc函数的副本
var refInnerFunc2 = outerFunc();
refInnerFunc2(); // return 20 不同副本中变量privateAttr的值是独立的。
当一个javascript函数返回时,js解析器会保留它作用域内的所有变量和函数。
闭包(Closure)这个词形象地描述了函数作用域现场被“封闭包存”起来这一行为。
直到该函数不再被其他对象引用,其作用域内的变量和函数才能被释放回收。
按照java回收机制的解释,方法内的局部变量在该方法被执行完毕后,
如果不再被其他对象引用,垃圾回收器可自行选择适当的时机回收这些局部变量。
但js的垃圾回收机制和java不同,上述js代码的执行结果便可以证明这一点。
js的垃圾回收机制同样是对不再被其他对象引用的变量或方法进行回收,
但因为js的引用不仅可指向变量,也可指向函数,在上述js代码中,
只要指向函数 innerFunc 的引用 refInnerFunc 还没有被设为null,
那么处在函数 innerFunc 作用域内的局部变量都不会被js垃圾回收器回收。
局部变量 privateAttr 被认为处在一个安全且相对封闭的“闭包”环境中,
访问它的唯一方法是通过调用处在同一作用域下的 innerFunc 函数来进行。
直到 innerFunc 函数不再被其他对象引用,其作用域内的变量和函数才能被释放回收。