JS常見內(nèi)存泄漏及解決方案解析
內(nèi)存泄漏?
官方解釋:內(nèi)存泄漏(Memory Leak)是指程序中己動(dòng)態(tài)分配的堆內(nèi)存由于某種原因程序未釋放或無法釋放,造成系統(tǒng)內(nèi)存的浪費(fèi),導(dǎo)致程序運(yùn)行速度減慢甚至系統(tǒng)崩潰等嚴(yán)重后果。
通俗點(diǎn)就是指由于疏忽或者錯(cuò)誤造成程序未能釋放已經(jīng)不再使用的內(nèi)存,不再用到的內(nèi)存卻沒有及時(shí)釋放,從而造成內(nèi)存上的浪費(fèi)。
避免內(nèi)存泄漏?
在局部作用域中,等函數(shù)執(zhí)行完畢,變量就沒有存在的必要了,垃圾回收機(jī)制很虧地做出判斷并且回收,但是對(duì)于全局變量,很難判斷什么時(shí)候不用這些變量,無法正?;厥眨凰?,盡量少使用全局變量。在使用閉包的時(shí)候,就會(huì)造成嚴(yán)重的內(nèi)存泄漏,因?yàn)殚]包中的局部變量,會(huì)一直保存在內(nèi)存中。
內(nèi)存溢出?
當(dāng)程序運(yùn)行需要的內(nèi)存超過了剩余的內(nèi)存時(shí), 就出拋出內(nèi)存溢出的錯(cuò)誤。
例如下面的代碼,謹(jǐn)慎試用,可能會(huì)卡窗口。。。。
var obj = {} for (var i = 0; i < 100000; i++) { obj[i] = new Array(10000000) } console.log('------')
常見的js內(nèi)存泄漏
1. 意外的全局變量
在js中,一個(gè)未聲明變量的使用,會(huì)在全局對(duì)象中創(chuàng)建一個(gè)新的變量;在瀏覽器環(huán)境下,全局對(duì)象就是window:
function foo() { a = 'test' } // 上面的寫法等價(jià)于 function foo() { window.a = 'test' }
function foo() { this.a = 'test' // 函數(shù)自身發(fā)生調(diào)用,this指向全局對(duì)象window } foo();
上面的a變量應(yīng)該是foo()內(nèi)部作用域變量的引用,由于沒有使用var來聲明這個(gè)變量,這時(shí)變量a就被創(chuàng)建成了全局變量,這個(gè)就是錯(cuò)誤的,會(huì)導(dǎo)致內(nèi)存泄漏。
解決方式: 在js文件開頭添加 ‘use strict',開啟嚴(yán)格模式。(或者一般將使用過后的全局變量設(shè)置為 null 或者將它重新賦值,這個(gè)會(huì)涉及的緩存的問題,需要注意)
<script> "use strict"; console.log("這是嚴(yán)格模式。"); </script> <script> console.log("這是正常模式。"); </script>
2. 計(jì)時(shí)器和回調(diào)函數(shù)timers
定時(shí)器setInterval或者setTimeout在不需要使用的時(shí)候,沒有被clear,導(dǎo)致定時(shí)器的回調(diào)函數(shù)及其內(nèi)部依賴的變量都不能被回收,這就會(huì)造成內(nèi)存泄漏。
解決方式:當(dāng)不需要interval或者timeout的時(shí)候,調(diào)用clearInterval或者clearTimeout
3. DOM泄漏
1)給DOM對(duì)象添加的屬性是一個(gè)對(duì)象的引用
var a = {};
document.getElementById('id').diyProp = a;
解決方法:在window.onload時(shí)間中加上 document.getElementById('id').diyProp = null;
2)元素引用沒有清理
var a = document.getElementById('id');
document.body.removeChild(a);
// 不能回收,因?yàn)榇嬖谧兞縜對(duì)它的引用。雖然我們用removeChild移除了,但是還在對(duì)象里保存著#的引用,即DOM元素還在內(nèi)存里面。
解決方法: a = null;
3)事件的綁定沒有移除
解決方法: 移除時(shí)間的監(jiān)聽
4. js閉包
閉包在IE6下會(huì)造成內(nèi)存泄漏,但是現(xiàn)在已經(jīng)無須考慮了。值得注意的是閉包本身不會(huì)造成內(nèi)存泄漏,但閉包過多很容易導(dǎo)致內(nèi)存泄漏。閉包會(huì)造成對(duì)象引用的生命周期脫離當(dāng)前函數(shù)的上下文,如果閉包如果使用不當(dāng),可以導(dǎo)致環(huán)形引用(circular reference),類似于死鎖,只能避免,無法發(fā)生之后解決,即使有垃圾回收也還是會(huì)內(nèi)存泄露。
這個(gè),另外找個(gè)時(shí)間詳細(xì)說明一下,這里就不贅述了
5. console
控制臺(tái)日志記錄對(duì)總體內(nèi)存內(nèi)置文件的影響,也是個(gè)重大的問題,同時(shí)也是容易被忽略的。記錄錯(cuò)誤的對(duì)象,可以將大量的數(shù)據(jù)保留在內(nèi)存中。傳遞給console.log的對(duì)象是不能被垃圾回收,所以沒有去掉console.log可能會(huì)存在內(nèi)存泄漏
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
JS實(shí)現(xiàn)的倒計(jì)時(shí)恢復(fù)按鈕點(diǎn)擊功能【可用于協(xié)議閱讀倒計(jì)時(shí)】
這篇文章主要介紹了JS實(shí)現(xiàn)的倒計(jì)時(shí)恢復(fù)按鈕點(diǎn)擊功能,可用于協(xié)議閱讀倒計(jì)時(shí),涉及javascript基于setInterval的時(shí)間定時(shí)觸發(fā)相關(guān)操作技巧,需要的朋友可以參考下2018-04-04微信小程序使用同聲傳譯實(shí)現(xiàn)語音識(shí)別功能
語音識(shí)別可以將語音精準(zhǔn)識(shí)別為文字,在很多場(chǎng)景中都可以使用,本文主要介紹了微信小程序使用同聲傳譯實(shí)現(xiàn)語音識(shí)別功能,分享給大家,感興趣的可以了解一下2021-06-06JavaScript實(shí)現(xiàn)簡(jiǎn)單獲取當(dāng)前網(wǎng)頁網(wǎng)址的方法
這篇文章主要介紹了JavaScript實(shí)現(xiàn)簡(jiǎn)單獲取當(dāng)前網(wǎng)頁網(wǎng)址的方法,通過location對(duì)象的href方法來獲取網(wǎng)址,非常簡(jiǎn)單實(shí)用,需要的朋友可以參考下2015-11-11canvas實(shí)現(xiàn)手機(jī)端用來上傳用戶頭像的代碼
這篇文章主要介紹了canvas實(shí)現(xiàn)手機(jī)端用來上傳用戶頭像的代碼代碼簡(jiǎn)單易懂非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下2016-10-10JavaScript兩種axios取消請(qǐng)求方式小結(jié)
本文主要介紹了JavaScript兩種axios取消請(qǐng)求方式小結(jié),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-03-03簡(jiǎn)易的JS計(jì)算器實(shí)現(xiàn)代碼
這篇文章主要為大家詳細(xì)介紹了JS簡(jiǎn)易的計(jì)算器實(shí)現(xiàn)代碼,,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-10-10構(gòu)建一個(gè)JavaScript插件系統(tǒng)
這篇文章主要介紹了如何構(gòu)建一個(gè)JavaScript插件系統(tǒng),幫助大家更好的理解和使用JavaScript,感興趣的朋友可以了解下2020-10-10