本节谈论如何让垃圾回收机制更高效地工作。
5.2.1 作用域
在Javascript中能形成作用域的有函数调用,全局作用域。
举个例子:
var foo = function () {
var local = {};
};
foo函数在执行过程中,local会被分配在新生代空间,在函数执行完,它会在下次垃圾回收时立即释放。
1)标识符的查找
标识符就是变量名,Javascript在查找标识符时,它会先查找当前作用域里的变量,如果查找不到就向上级作用域查找,直到查到为止。
2)作用域链
var foo = function () {
var local = 'local var';
var bar = function () {
var local = 'another var';
var baz = function () {
console.log(local);
};
baz();
};
bar();
};
foo();
local变量baz在当前作用域找不到,会继续在bar()作用域找,一直到全局作用域。这样查找使得作用域像一条链条,由于标识符的查找方向是向上的,所以变量只能向外访问,而不能向内访问。
3)变量的主动释放
如果变量是全局变量,那么它的生命周期会直到进程退出才能释放。如果想让该变量快速释放,可以通过delete或者直接通过新的变量值覆盖原有变量即可。
5.2.2 闭包
刚刚提到,作用域链上的对象访问只能向上,这样外部无法向内访问。
var foo = function () {
var local = "局部变量";
(function () {
console.log(local);
}());
};
下面代码中,会得到local未定义的异常。
var foo = function () {
(function () {
var local = "局部变量";
}());
console.log(local);
};
在Javascript中,实现外部作用域访问内部作用域中变量的方法叫做闭包。这得益于高阶函数的特性:函数可以作为参数或返回值。
代码如下:
var foo = function () {
var bar = function () {
var local = "局部变量";
return function () {
return local;
};
};
var baz = bar();
console.log(baz());
};
一般来说,函数执行完,内部变量就会随着作用域的销毁而被回收。但是这里返回的是一个匿名函数,该函数具有访问local的条件。虽然函数后续执行时,仍旧无法直接访问local,但是若要访问它,只要通过这个中间函数稍作周转即可。