垃圾回收
JavaScript 中的内存管理是自动执行的,而且是不可见的。当我们创建了变量,而且不再使用它们时,JavaScript 引擎 就会(按照固定的时间间隔周期性)检测回收清理这些变量。
如果要往对象上添加数据,又不想干扰垃圾回收机制,就可以使用 WeakMap
垃圾回收算法
标记-清除 法
-
标记阶段:从根集合出发,将所有活动对象及其子对象打上标记
-
清除阶段:遍历堆,将非活动对象(未打上标记)的连接到空闲链表上
引用计数法:检测到引用计数为 0 则认为不再使用该值,被回收
引起内存泄漏的情况
不再用到的内存,没有及时释放,就叫做内存泄漏。如果一个值不再需要了,引用数却不为 0,垃圾回收机制无法释放这块内存,从而导致内存泄漏。
-
全局变量。
function fn() { bar = "123"; }
解决方案:使用严格模式,且内部变量采用 var 等标记。
-
闭包
function foo() { var a = 2; function bar() { console.log(a); } return bar; } var bar = foo(); bar(); //bar指向的对象会一直存在堆内存中
解决方案:
function foo() { var a = 2; function bar() { console.log(a); } return bar; } var bar = foo(); bar(); bar = null; //(或者是直接将内部函数定义在外部,解除闭包)
-
dom 清空或删除时,事件未清除。
var farther = document.getElementById("farther"); // 父元素 var child = document.getElementById("child"); // 子元素 function handle() { alert("clicked"); } child.addEventListener("click", handle, false); farther.removeChild(child); // 我们上一步虽然删除了 dom 元素,但是这一步之后依然可以执行点击事件。 document.body.appendChild(link);
解决方案
child = null;
-
定时器
如果在定时器中存在 DOM 的引用,删除 DOM 后,依然在内存中存在这个 DOM 元素。
解决方案: 手动删除 定时器 和 DOM 。