摘要:前言內存泄漏指由于疏忽或錯誤造成程序未能釋放已經不再使用的內存。這里就講一些常見會帶來內存泄露的原因。解決方案和都設為。
前言
內存泄漏指由于疏忽或錯誤造成程序未能釋放已經不再使用的內存。內存泄漏并非指內存在物理上的消失,而是應用程序分配某段內存后,由于設計錯誤,導致在釋放該段內存之前就失去了對該段內存的控制,從而造成了內存的浪費。這里就講一些常見會帶來內存泄露的原因。
0. 全局變量JavaScript自由的其中一種方式是它可以處理沒有聲明的變量:一個未聲明的變量的引用在全局對象中創建了一個新變量。在瀏覽器的環境中,全局對象是window。
function foo(){ name = "前端曰"; } // 其實是把name變量掛載在window對象上 function foo(){ window.name = "前端曰"; } // 又或者 function foo(){ this.name = "前端曰"; } foo() // 其實這里的this就是指向的window對象
這樣無意中一個意外的全局變量就被創建了,為了阻止這種錯誤發生,在你的Javascript文件最前面添加 "use strict;" 。這開啟了解析JavaScript的阻止意外全局的更嚴格的模式?;蛘咦约鹤⒁夂米兞康亩x!
1. 循環引用在js的內存管理環境中,對象 A 如果有訪問對象 B 的權限,叫做對象 A 引用對象 B。引用計數的策略是將“對象是否不再需要”簡化成“對象有沒有其他對象引用到它”,如果沒有對象引用這個對象,那么這個對象將會被回收 。
function func() { let obj1 = {}; let obj2 = {}; obj1.a = obj2; // obj1 引用 obj2 obj2.a = obj1; // obj2 引用 obj1 }
當函數 func 執行結束后,返回值為 undefined,所以整個函數以及內部的變量都應該被回收,但根據引用計數方法,obj1 和 obj2 的引用次數都不為 0,所以他們不會被回收。要解決循環引用的問題,最好是在不使用它們的時候手工將它們設為空。
解決方案:obj1 和 obj2 都設為 null 。
2. 老生常談的閉包閉包:匿名函數可以訪問父級作用域的變量。
var names = (function(){ var name = "js-say"; return function(){ console.log(name); } })()
閉包會造成對象引用的生命周期脫離當前函數的上下文,如果閉包如果使用不當,可以導致環形引用(circular reference),類似于死鎖,只能避免,無法發生之后解決,即使有垃圾回收也還是會內存泄露。
3. 被遺忘的延時器/定時器在我們的日常需求中,可能會經常試用到 setInterval/setTimeout ,但是使用完之后通常忘記清理。
var someResource = getData(); setInterval(function() { var node = document.getElementById("Node"); if(node) { // 處理 node 和 someResource node.innerHTML = JSON.stringify(someResource)); } }, 1000);
setInterval/setTimeout 中的 this 指向的是window對象,所以內部定義的變量也掛載到了全局;if 內引用了 someResource 變量,如果沒有清除 setInterval/setTimeout 的話someResource 也得不到釋放;同理其實 setTimeout 也一樣。所以我們用完需要記得去 clearInterval/clearTimeout。
4. DOM引起的內存泄露未清除DOM引用
var refA = document.getElementById("refA"); document.body.removeChild(refA); // #refA不能回收,因為存在變量refA對它的引用。將其對#refA引用釋放,但還是無法回收#refA。
解決方案:refA = null 。
DOM對象添加的屬性是一個對象的引用
var MyObject = {}; document.getElementById("myDiv").myProp = MyObject;
解決方案:在頁面 onunload 事件中釋放 document.getElementById("myDiv").myProp = null; 。
DOM被刪除或清空沒有清楚綁定事件這種情況應該是比較常見的,同時也應該是比較容易被忽略的。
給DOM對象綁定事件
var btn = document.getElementById("myBtn"); btn.onclick = function(){ document.getElementById("myDiv").innerHTML = "wechat: js-say"; } document.body.removeChild(btn); btn = null;
這里把DOM移除了,但是綁定的事件仍沒被移除,會引起內存泄露所以需要清除事件。
var btn = document.getElementById("myBtn"); btn.onclick = function(){ btn.onclick = null; document.getElementById("myDiv").innerHTML = "wechat: js-say"; } document.body.removeChild(btn); btn = null;小廣告
我自己運營的公眾號,記錄我自己的成長!
每周至少一篇博客,拒絕拖延從我做起!
公眾號:前端曰
公眾號ID:js-say
ps:是(yue)不是(ri)
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/104352.html
摘要:解決方式是,當我們不使用它們的時候,手動切斷鏈接淘汰把和對象轉為了真正的對象,避免了使用這種垃圾收集策略,消除了以下常見的內存泄漏的主要原因。以上參考資料高程垃圾收集類內存泄漏及如何避免內存泄露及解決方案詳解類內存泄漏及如何避免 showImg(http://ww1.sinaimg.cn/large/005Y4rCogy1ft1ikzcqzqj30ka0et77a.jpg); 前言 起...
摘要:應用常見安全漏洞一覽注入注入就是通過給應用接口傳入一些特殊字符,達到欺騙服務器執行惡意的命令。此外,適當的權限控制不曝露必要的安全信息和日志也有助于預防注入漏洞。 web 應用常見安全漏洞一覽 1. SQL 注入 SQL 注入就是通過給 web 應用接口傳入一些特殊字符,達到欺騙服務器執行惡意的 SQL 命令。 SQL 注入漏洞屬于后端的范疇,但前端也可做體驗上的優化。 原因 當使用外...
摘要:應用常見安全漏洞一覽注入注入就是通過給應用接口傳入一些特殊字符,達到欺騙服務器執行惡意的命令。此外,適當的權限控制不曝露必要的安全信息和日志也有助于預防注入漏洞。 web 應用常見安全漏洞一覽 1. SQL 注入 SQL 注入就是通過給 web 應用接口傳入一些特殊字符,達到欺騙服務器執行惡意的 SQL 命令。 SQL 注入漏洞屬于后端的范疇,但前端也可做體驗上的優化。 原因 當使用外...
摘要:導語智能手機發展到今天已經有十幾個年頭,手機的軟硬件都已經發生了翻天覆地的變化,特別是陣營,從一開始的一兩百到今天動輒,內存。恰好最近做了內存優化相關的工作,這里也對內存優化相關的知識做下總結。 導語 智能手機發展到今天已經有十幾個年頭,手機的軟硬件都已經發生了翻天覆地的變化,特別是Android陣營,從一開始的一兩百M到今天動輒4G,6G內存。然而大部分的開發者觀看下自己的異常上報系...
閱讀 3146·2021-10-12 10:11
閱讀 1851·2021-08-16 10:59
閱讀 2862·2019-08-30 15:55
閱讀 1236·2019-08-30 14:19
閱讀 2046·2019-08-29 17:03
閱讀 2481·2019-08-29 16:28
閱讀 3229·2019-08-26 13:47
閱讀 2897·2019-08-26 13:36