什么是內(nèi)存泄露? 已經(jīng)不再使用的內(nèi)存未能被程序釋放,叫內(nèi)存泄露(memory leak)。 內(nèi)存泄露會帶來什么樣的后果? 內(nèi)存泄露會因?yàn)闇p少可用內(nèi)存數(shù)量從而降低計算機(jī)性能,嚴(yán)重的可能導(dǎo)致設(shè)備停止正常工作,或者應(yīng)用程序崩潰。 什么情況下出現(xiàn)內(nèi)存泄漏? 首先了解一下垃圾回收:垃圾回收(英語:Garbage Collection,縮寫為GC)在計算器科學(xué)中是一種自動的存儲器管理機(jī)制。當(dāng)一個計算機(jī)上的動態(tài)存儲器不再需要時,就應(yīng)該予以釋放,以讓出存儲器,這種存儲器資源管理,稱為垃圾回收。 當(dāng)一塊內(nèi)存不再用到,但是垃圾回收機(jī)制又無法釋放這塊內(nèi)存的時候,就導(dǎo)致內(nèi)存泄漏。 出現(xiàn)內(nèi)存泄露的的幾種常見情況: 1、全局變量 由于JavaScript對未聲明變量的處理方式是在全局對象上創(chuàng)建該變量的引用。如果在瀏覽器中,全局對象就是window對象。 變量在窗口關(guān)閉或重新刷新頁面之前都不會被釋放,如果未聲明的變量緩存大量的數(shù)據(jù),就會導(dǎo)致內(nèi)存泄露。 a = '我是未聲明的變量a,我緩存了數(shù)據(jù),如果數(shù)據(jù)足夠大的話,就會內(nèi)存泄漏' 2、閉包(closures): js函數(shù)內(nèi)可以直接讀取全局變量,但是函數(shù)外不能讀取函數(shù)內(nèi)的局部變量。這時候在函數(shù)f1內(nèi)再聲明一個函數(shù)f2調(diào)用局部變量, 然后返回函數(shù)f2,在f1的外部聲明一個變量result賦值為f1,再調(diào)用result,就是一個閉包的例子。 function f1(){ var n = 999; function f2(){ alert(n); } return f2; } var result = f1(); result(); // 999 閉包可以讀取函數(shù)內(nèi)部的變量,然后讓這些變量始終保存在內(nèi)存中。如果在使用結(jié)束后沒有將局部變量清除,就可能導(dǎo)致內(nèi)存泄露。 3、事件監(jiān)聽(EventListener) 對同一個事件重復(fù)監(jiān)聽,但是忘記移除,會導(dǎo)致內(nèi)存泄露。 4、其他原因 console.log打印的對象不能被垃圾回收,可能會導(dǎo)致內(nèi)存泄露。 setInterval也可能會導(dǎo)致內(nèi)存泄露。 前端如何檢查內(nèi)存泄露? (1).使用Chrome的開發(fā)者工具profiles來進(jìn)行快照對比。 (2).如果是在Node環(huán)境下,可以用Node提供的process.memoryUsage()方法來檢查內(nèi)存泄露: rss (resident set size) : 所有內(nèi)存占用,包括指令區(qū)和堆棧。 heapTotal : "堆"占用的內(nèi)存,包括用到的和未用到的。 heapUsed : 用到的堆。 external : V8引擎內(nèi)部C++對象占用的內(nèi)存。 判斷內(nèi)存泄露以heapUsed為準(zhǔn)。
如何處理內(nèi)存泄漏? 變量導(dǎo)致的內(nèi)存泄露,將變量清除 a = null 即可。 事件監(jiān)聽導(dǎo)致的內(nèi)存泄露,監(jiān)聽后移除即可。 |
|