在很多基于虚拟机的程序语言中,都有析构方法用来在对象被清除之后显式地进行内存垃圾的回收以清理内存。但 JavaScript 没有析构方法用来显式地清理内存,用于执行 JavaScript 程序的解释引擎是自动管理内存的,自动管理内存意味着定期进行内存垃圾的回收。
虽然解释引擎会定期进行内存垃圾的回收,但用户也应该养成良好的习惯,当一个变量不再使用时,应该为它赋值为 null ,这样将会告诉解释引擎该变量符合垃圾回收条件;或者使用 delete 语句删除对象的属性,虽然对象不能被删除,但是使该对象的属性所引用的内存也符合垃圾回收条件,从而可以节省内存。
解释引擎定期从内存中清除程序中不再引用的所有对象和变量,这种操作称为垃圾回收。垃圾回收的基本原理是,当对象不具有指向它的引用时,即可对其进行垃圾回收,并会在下次执行垃圾回收系统时恢复内存。
例如下面的代码创建一个新 Object 对象,并将对该对象的引用分配给变量 o :
var o = new Object();
当为 o 赋值为 null 或另一个值时,该变量与 Object 对象的引用关系被断开,当解释引擎下次执行垃圾回收系统时, Object 对象会被从内存中删除,从而节省了内存,代码如下:
o = null;
o = '$1 意一个值 ';
对象的属性也可以引用另外一个对象,例如下面的代码, o 的属性 birthDay 引用了另外一个 Date 对象:
var o = new Object();
o.birthDay = new Date(1980, 7, 5);
这时,可以使用 delete 语句删除对象的属性,从而使属性与 Date 对象的引用关系断开,当解释引擎下次执行垃圾回收系统时, Date 对象会被从内存中删除,代码如下:
delete o.birthDay;
console.log(o.birthDay); // 删除后的值为 undefined
当然,如果此时将 o 赋值为 null 或另一个值,可以使 Object 和 Date 对象均处于可以被垃圾回收的状态。
数组元素也可以引用对象,当该元素不再使用时,应该使用 delete 语句将其删除,如果数组不再使用,那么应该将引用数组的变量设置为 null 。
例如下面的代码,第二个元素引用了一个 Date 对象,当不再使用时,就调用 delete 语句删除该元素,但数组长度不会发生变化:
var tom = new Array('male', new Date(1980, 7, 5));
delete tom[1];
console.log(tom[1]); // 输出 undefined
console.log(tom.length); // 输出 2
如果数组不再使用,那么:
tom = null;
对于复合数组,也遵守相同的规则,代码如下:
var tom = new Array();
tom['sex'] = 'male';
tom['birthday'] = new Date(1980, 7, 5); // 如果不再使用 birthday 元素
delete tom['birthday'];
console.log(tom['birthday']); // 输出 undefined
如果复合数组不再使用,那么执行:
tom = null;
最佳实践。
在一些文档中也提到:当不再使用时,应该将函数中定义的对象变量也赋值为 null ,以使其符合垃圾回收条件。这是一种错误的提法,因为变量在函数中的生存周期仅限于函数自身,当函数执行结束后,该变量自行消失,无需再将变量赋值为 null 。