JavaScript的垃圾回收机制与内存泄漏问题讲解

本篇内容介绍了“JavaScript的垃圾回收机制与内存泄漏问题讲解”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!

创新互联专注于尼开远网站建设服务及定制,我们拥有丰富的企业做网站经验。 热诚为您提供尼开远营销型网站建设,尼开远网站制作、尼开远网页设计、尼开远网站官网定制、小程序开发服务,打造尼开远网络公司原创品牌,更为您提供尼开远网站排名全网营销落地服务。

常用的两种算法:

引用计数(新版浏览器已弃用,弃用原因:会出现循环引用的情况,无法进行垃圾回收,导致内存泄漏)

标记清除

引用计数法

引用计数,顾名思义一个对象是否有指向它的引用,即看栈中是否有指向要释放的该块堆内存中的地址,如果没有,则该块内存是不需要的,可以进行释放,即垃圾回收

下面引用大佬的一个简短例子来说明情况

// 创建一个对象person,他有两个指向属性age和name的引用var person = {    age: 12,    name: 'aaaa'};
person.name = null; // 虽然name设置为null,但因为person对象还有指向name的引用,因此name不会回收
var p = person; person = 1;         //原来的person对象被赋值为1,但因为有新引用p指向原person对象,因此它不会被回收
p = null;           //原person对象已经没有引用,很快会被回收

缺点:引用计数有一个致命的问题,那就是循环引用

当两个对象相互引用,尽管他们已不再使用,但是垃圾回收器不会进行回收,最终可能会导致内存泄露。

function cycle() {    var o1 = {};//1    var o2 = {};//1    o1.a = o2;//2    o2.a = o1; //2    return "cycle reference!"}
cycle();

JavaScript的垃圾回收机制与内存泄漏问题讲解

cycle函数执行完成之后,对象o1o2实际上已经不再需要了,但根据引用计数的原则,他们之间的相互引用依然存在,因此这部分内存不会被回收。所以现代浏览器不再使用这个算法。

但是IE依旧使用。

var div = document.createElement("div");div.onclick = function() {   console.log("click");};

上面的写法很常见,但是上面的例子就是一个循环引用。

变量div有事件处理函数的引用,同时事件处理函数也有div的引用,因为div变量可在函数内被访问,所以循环引用就出现了。

标记清除(常用)

文章里写的是:标记清除算法将“不再使用的对象”定义为“无法到达的对象”。即从根部(在JS中就是全局对象)出发定时扫描内存中的对象,凡是能从根部到达的对象,保留。那些从根部出发无法触及到的对象被标记为不再使用,稍后进行回收。

我这里个人理解:不在原型链上的,不能从全局对象链找到的对象,会被认为是无法到达的对象(也可能我自己理解有误,忘读者指出),比如说下面这个例子

var a = {}  // 这里的a是挂在全局对象上的a = null  // 这里a之前存放指向{}的地址变成了null// 此时{}是无法找到的,通过全局对象找到a也无法到达{},因此{}会被垃圾回收

无法触及的对象包含了没有引用的对象这个概念,但反之未必成立。

所以上面的例子就可以正确被垃圾回收处理了。

所以现在对于主流浏览器来说,只需要切断需要回收的对象与根部的联系,就能进行垃圾回收

下面还是引用大佬的例子

最常见的内存泄露一般都与DOM元素绑定有关:

email.message = document.createElement(“div”);displayList.appendChild(email.message);
// 稍后从displayList中清除DOM元素displayList.removeAllChildren();

上面代码中,div元素已经从DOM树中清除,但是该div元素还绑定在email对象中,所以如果email对象存在,那么该div元素就会一直保存在内存中

“JavaScript的垃圾回收机制与内存泄漏问题讲解”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注创新互联网站,小编将为大家输出更多高质量的实用文章!


当前文章:JavaScript的垃圾回收机制与内存泄漏问题讲解
文章出自:http://hbruida.cn/article/jjijii.html