摘要:前言內(nèi)存泄漏指由于疏忽或錯誤造成程序未能釋放已經(jīng)不再使用的內(nèi)存。這里就講一些常見會帶來內(nèi)存泄露的原因。解決方案和都設為。
前言
內(nèi)存泄漏指由于疏忽或錯誤造成程序未能釋放已經(jīng)不再使用的內(nèi)存。內(nèi)存泄漏并非指內(nèi)存在物理上的消失,而是應用程序分配某段內(nèi)存后,由于設計錯誤,導致在釋放該段內(nèi)存之前就失去了對該段內(nèi)存的控制,從而造成了內(nèi)存的浪費。這里就講一些常見會帶來內(nèi)存泄露的原因。
0. 全局變量JavaScript自由的其中一種方式是它可以處理沒有聲明的變量:一個未聲明的變量的引用在全局對象中創(chuàng)建了一個新變量。在瀏覽器的環(huán)境中,全局對象是window。
function foo(){ name = "前端曰"; } // 其實是把name變量掛載在window對象上 function foo(){ window.name = "前端曰"; } // 又或者 function foo(){ this.name = "前端曰"; } foo() // 其實這里的this就是指向的window對象
這樣無意中一個意外的全局變量就被創(chuàng)建了,為了阻止這種錯誤發(fā)生,在你的Javascript文件最前面添加 "use strict;" 。這開啟了解析JavaScript的阻止意外全局的更嚴格的模式?;蛘咦约鹤⒁夂米兞康亩x!
1. 循環(huán)引用在js的內(nèi)存管理環(huán)境中,對象 A 如果有訪問對象 B 的權限,叫做對象 A 引用對象 B。引用計數(shù)的策略是將“對象是否不再需要”簡化成“對象有沒有其他對象引用到它”,如果沒有對象引用這個對象,那么這個對象將會被回收 。
function func() { let obj1 = {}; let obj2 = {}; obj1.a = obj2; // obj1 引用 obj2 obj2.a = obj1; // obj2 引用 obj1 }
當函數(shù) func 執(zhí)行結束后,返回值為 undefined,所以整個函數(shù)以及內(nèi)部的變量都應該被回收,但根據(jù)引用計數(shù)方法,obj1 和 obj2 的引用次數(shù)都不為 0,所以他們不會被回收。要解決循環(huán)引用的問題,最好是在不使用它們的時候手工將它們設為空。
解決方案:obj1 和 obj2 都設為 null 。
2. 老生常談的閉包閉包:匿名函數(shù)可以訪問父級作用域的變量。
var names = (function(){ var name = "js-say"; return function(){ console.log(name); } })()
閉包會造成對象引用的生命周期脫離當前函數(shù)的上下文,如果閉包如果使用不當,可以導致環(huán)形引用(circular reference),類似于死鎖,只能避免,無法發(fā)生之后解決,即使有垃圾回收也還是會內(nèi)存泄露。
3. 被遺忘的延時器/定時器在我們的日常需求中,可能會經(jīng)常試用到 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對象,所以內(nèi)部定義的變量也掛載到了全局;if 內(nèi)引用了 someResource 變量,如果沒有清除 setInterval/setTimeout 的話someResource 也得不到釋放;同理其實 setTimeout 也一樣。所以我們用完需要記得去 clearInterval/clearTimeout。
4. DOM引起的內(nèi)存泄露未清除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移除了,但是綁定的事件仍沒被移除,會引起內(nèi)存泄露所以需要清除事件。
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)
文章版權歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://www.ezyhdfw.cn/yun/104352.html
摘要:解決方式是,當我們不使用它們的時候,手動切斷鏈接淘汰把和對象轉(zhuǎn)為了真正的對象,避免了使用這種垃圾收集策略,消除了以下常見的內(nèi)存泄漏的主要原因。以上參考資料高程垃圾收集類內(nèi)存泄漏及如何避免內(nèi)存泄露及解決方案詳解類內(nèi)存泄漏及如何避免 showImg(http://ww1.sinaimg.cn/large/005Y4rCogy1ft1ikzcqzqj30ka0et77a.jpg); 前言 起...
摘要:應用常見安全漏洞一覽注入注入就是通過給應用接口傳入一些特殊字符,達到欺騙服務器執(zhí)行惡意的命令。此外,適當?shù)臋嘞蘅刂撇黄芈侗匾陌踩畔⒑腿罩疽灿兄陬A防注入漏洞。 web 應用常見安全漏洞一覽 1. SQL 注入 SQL 注入就是通過給 web 應用接口傳入一些特殊字符,達到欺騙服務器執(zhí)行惡意的 SQL 命令。 SQL 注入漏洞屬于后端的范疇,但前端也可做體驗上的優(yōu)化。 原因 當使用外...
摘要:應用常見安全漏洞一覽注入注入就是通過給應用接口傳入一些特殊字符,達到欺騙服務器執(zhí)行惡意的命令。此外,適當?shù)臋嘞蘅刂撇黄芈侗匾陌踩畔⒑腿罩疽灿兄陬A防注入漏洞。 web 應用常見安全漏洞一覽 1. SQL 注入 SQL 注入就是通過給 web 應用接口傳入一些特殊字符,達到欺騙服務器執(zhí)行惡意的 SQL 命令。 SQL 注入漏洞屬于后端的范疇,但前端也可做體驗上的優(yōu)化。 原因 當使用外...
摘要:導語智能手機發(fā)展到今天已經(jīng)有十幾個年頭,手機的軟硬件都已經(jīng)發(fā)生了翻天覆地的變化,特別是陣營,從一開始的一兩百到今天動輒,內(nèi)存。恰好最近做了內(nèi)存優(yōu)化相關的工作,這里也對內(nèi)存優(yōu)化相關的知識做下總結。 導語 智能手機發(fā)展到今天已經(jīng)有十幾個年頭,手機的軟硬件都已經(jīng)發(fā)生了翻天覆地的變化,特別是Android陣營,從一開始的一兩百M到今天動輒4G,6G內(nèi)存。然而大部分的開發(fā)者觀看下自己的異常上報系...
閱讀 3201·2021-10-12 10:11
閱讀 1920·2021-08-16 10:59
閱讀 2935·2019-08-30 15:55
閱讀 1296·2019-08-30 14:19
閱讀 2093·2019-08-29 17:03
閱讀 2529·2019-08-29 16:28
閱讀 3290·2019-08-26 13:47
閱讀 2945·2019-08-26 13:36