视频1 视频21 视频41 视频61 视频文章1 视频文章21 视频文章41 视频文章61 推荐1 推荐3 推荐5 推荐7 推荐9 推荐11 推荐13 推荐15 推荐17 推荐19 推荐21 推荐23 推荐25 推荐27 推荐29 推荐31 推荐33 推荐35 推荐37 推荐39 推荐41 推荐43 推荐45 推荐47 推荐49 关键词1 关键词101 关键词201 关键词301 关键词401 关键词501 关键词601 关键词701 关键词801 关键词901 关键词1001 关键词1101 关键词1201 关键词1301 关键词1401 关键词1501 关键词1601 关键词1701 关键词1801 关键词1901 视频扩展1 视频扩展6 视频扩展11 视频扩展16 文章1 文章201 文章401 文章601 文章801 文章1001 资讯1 资讯501 资讯1001 资讯1501 标签1 标签501 标签1001 关键词1 关键词501 关键词1001 关键词1501 专题2001
内存泄漏是什么以及如何解决
2020-11-27 19:27:11 责编:小采
文档
 内存泄漏指的是当一个对象不起作用时应该被回收时却因为另一个对象对它的引用而导致它不能被回收,留在了堆内存中就称为内存泄漏。常见的有意外全局变量,DOM泄漏以及循环引用等

【推荐课程:JavaScript教程】

内存泄漏

内存泄漏一般指的是当一个对象已经没有作用了应该被回收时,另外一个正在使用的对象因对它的引用从而导致它不能被回收,这个不能被回收的对象停留在了堆内存中,这就造成了内存泄漏

当一个对象已经不需要再使用本该被回收时,另外一个正在使用的对象持有它的引用从而导致它不能被回收,这导致本该被回收的对象不能被回收而停留在堆内存中,这就产生了内存泄漏

常见的内存泄漏:

1、意外的全局变量

Js处理未定义变量的方式:未定义的变量会在全局对象创建一个新变量,在浏览器中,全局对象是window。

function foo(arg) { 
bar = "this is a hidden global variable"; //等同于window.bar="this is a hidden global variable"
this.bar2= "potential accidental global";//这里的this 指向了全局对象(window),
等同于window.bar2="potential accidental global"}

解决方法:在JavaScript程序中添加,开启严格模式'use strict',可以有效地避免上述问题。

注意:用来临时存储大量数据的全局变量,在确保处理完这些数据后要将其设置为null或者重新赋值。

2、DOM泄漏

在浏览器中DOM和JS所采用的引擎是不一样的,DOM采用的是渲染引擎,而JS采用的是v8引擎,所以在用JS操作DOM时会比较耗费性能,所以为了减少DOM的操作,我们会采用变量引用的方式会将其缓存在当前环境。如果在进行一些删除、更新操作之后,可能会忘记释放已经缓存的DOM因此造成了内存泄漏

例:对没有清理的DOM元素引用

var refA = document.getElementById('refA');
document.body.removeChild(refA); // #refA不能回收,因为存在变量refA对它的引用。
将其对#refA引用释放,但还是无法回收#refA。

解决办法:设置refA = null;

3、被遗忘的计时器和回调函数

var someResource = getData();
setInterval(function() {
 var node = document.getElementById('Node');
 if(node) {
 node.innerHTML = JSON.stringify(someResource));
 }
}, 1000);

这样的代码很常见, 如果id为Node的元素从DOM中移除, 该定时器仍会存在, 同时, 因为回调函数中包含对someResource的引用, 定时器外面的someResource也不会被释放

4、循环引用

在js的内存管理环境中,如果对象 A 对B有访问对象的权限,就称为对象 A 引用对象 B。引用的计数的策略就是看对象有没有其他对象引用到它,如果没有对象引用这个对象,那么这个对象将会被回收 。

var obj1 = { a: 1 }; // 一个对象(称之为 A)被创建,赋值给 obj1,A 的引用个数为 1 
var obj2 = obj1; // A 的引用个数变为 2 
 obj1 = 0; // A 的引用个数变为 1 
 obj2 = 0; // A 的引用个数变为 0,此时对象 A 就可以被垃圾回收了

但是引用计数有个最大的问题就是循环引用。

function func() { 
 var obj1 = {}; 
 var obj2 = {}; 
 obj1.a = obj2; // obj1 引用 obj2 
 obj2.a = obj1; // obj2 引用 obj1 }

当函数执行结束后,返回值为 undefined,所以整个函数以及内部的变量都应该被回收,但根据引用计数方法,obj1 和 obj2 的引用次数都不为 0,所以他们不会被回收。所以要解决这个问题可以设置它们的值为null

总结:

下载本文
显示全文
专题