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;
}

 

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