JavaScrtipt 内存泄漏

一、内存生命周期

  1. 内存分配:当我们申明变量、函数、对象的时候,系统会自动为他们分配内存
  2. 内存使用:即读写内存,也就是使用变量、函数等
  3. 内存回收:使用完毕,由垃圾回收机制自动回收不再使用的内存

 

 二、内存泄漏

内存泄漏:不再用到的内存,没有及时释放,就叫做内存泄漏(memory leak)。

 

三、检测内容泄漏的方法 

1.通过谷歌浏览器检测:

打开chrome检查,点击Performance,勾选Memory,点击左上角的Record小圆点,开始录制

 录制时进行一些用户基本操作,操作结束后点击stop按钮,结束录制,页面会呈现录制结果

 结果:

 

判定当前是否有内存泄漏

  1. 多次快照后,比较每次快照中内存的占用情况,如果呈上升趋势,那么可以认为存在内存泄漏
  2. 某次快照后,看当前内存占用的趋势图,如果走势不平稳,呈上升趋势,那么可以认为存在内存泄漏
  3. 经过一些反复测试后,你看到的是锯齿状的图形(有上有下),说明你的程序中有很多短时存在的对象。

只看JS Heap(堆内存)这条线:

 

2.通过node.js的process. memoryUsage()检测

console.log(process.memoryUsage());
// { 
// rss: 27709440,
// heapTotal: 5685248,
// heapUsed: 3449392,
// external: 8772 
// }
  • rss(resident set size):所有内存占用,包括指令区和堆栈。
  • heapTotal:"堆"占用的内存,包括用到的和没用到的。
  • heapUsed:用到的堆的部分。
  • external: V8 引擎内部的 C++ 对象占用的内存。

 

四、可能导致内存泄漏的案例

1.声明时内存泄漏

function fn() {
    a = 1;
}
fn();
console.log(a); // 1

解决:声明时使用var、let、const.

function fn() {
    let a = 1;
}
fn();
console.log(a); // a is not defined

 

2.this导致内存泄漏

function fn() {
    this.a = 1; // this指向全局对象window,导致内存泄漏
}
fn();
console.log(this.a); // 1

 

3.没清除setInterval导致内存泄漏

setInterval没有清除,仅仅清除dom元素,定时器依旧不断工作

<!DOCTYPE html>
<html>
<head>
	<title></title>
</head>
<body>
	<div>
		<p id="text"></p>
		<button id="btn">移除</button>
	</div>
	<script>
		window.onload = function() {
			let p  = document.getElementById('text');
			setInterval(function() {
				let time = new Date();
				p.innerHTML = JSON.stringify(time);
				console.log(111);
			}, 1000);

			let btn = document.getElementById('btn');
			btn.onclick = function() {
				p.remove();
			}
		}
	</script>
</body>
</html>

解决:删除定时器

<!DOCTYPE html>
<html>
<head>
	<title></title>
</head>
<body>
	<div>
		<p id="text"></p>
		<button id="btn">移除</button>
	</div>
	<script>
		window.onload = function() {
			let timer = null;
			let p  = document.getElementById('text');
			timer = setInterval(function() {
				let time = new Date();
				p.innerHTML = JSON.stringify(time);
				console.log(111);
			}, 1000);

			let btn = document.getElementById('btn');
			btn.onclick = function() {
				p.remove();
				clearInterval(timer);
			}
		}
	</script>
</body>
</html>

 

4.闭包导致内存泄漏

function Person() {
    this.name = 'John';
    this.age = 12;
}
Person.prototype.showName = function() {
    let _this = this; //this常驻于内存中,闭包里的变量会持续保存,没有清理就会一直占用内存
    return function() {
        return _this.name;
    }
}

解决方法:保存this的属性,用完要置空。

function Person() {
    this.name = 'John';
    this.age = 12;
}
Person.prototype.showName = function() {
    let name= this.name; //this常驻于内存中,闭包里的变量会持续保存,没有清理就会一直占用内存
    return function() {
        return name;
    }
    name = null;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章