欧美三区_成人在线免费观看视频_欧美极品少妇xxxxⅹ免费视频_a级毛片免费播放_鲁一鲁中文字幕久久_亚洲一级特黄

JavaScript 中的內存泄露模式

系統 2043 0

知道內存泄漏的起因,那么在 JavaScript中進行相應的防范就應該相當容易。在這篇文章中,作者 Kiran Sundar 和 Abhijeet Bhattacharya 將帶您親歷JavaScript中的循環引用的全部基本知識,向您介紹為何它們會在某些瀏覽器中產生問題,尤其是在結合了閉包的情況下。在了解了您應該引起注意的常見內存泄漏模式之后,您還將學到應對這些泄漏的諸多方法。

JavaScript是用來向 Web 頁面添加動態內容的一種功能強大的腳本語言。它尤其特別有助于一些日常任務,比如驗證密碼和創建動態菜單組件。JavaScript易學易用,但卻很容易在某些瀏覽器中引起內存的泄漏。在這個介紹性的文章中,我們解釋了 JavaScript中的泄漏由何引起,展示了常見的內存泄漏模式,并介紹了如何應對它們。

注意本文假設您已經非常熟悉使用 JavaScript 和 DOM 元素來開發 Web 應用程序。本文尤其適合使用 JavaScript 進行 Web應用程序開發的開發人員,也可供有興趣創建 Web 應用程序的客戶提供瀏覽器支持以及負責瀏覽器故障排除的人員參考。

我的瀏覽器存在泄漏么?
Internet Explorer 和 Mozilla Firefox 是兩個與 JavaScript 中的內存泄漏聯系最為緊密的瀏覽器。兩個瀏覽器中造成這種問題的“罪魁禍首”是用來管理 DOM 對象的組件對象模型。本機 windows COM 和 Mozilla's XPCOM 都使用引用計數的垃圾收集來進行內存分配和檢索。引用計數與用于 JavaScript的標記-清除式的垃圾收集并不總是能相互兼容。本文側重介紹的是如何應對 JavaScript 代碼中的內存泄漏。有關如何處理 Firefox 和IE 中 COM 層內存泄漏的更多信息,請參看 參考資料 。

JavaScript 中的內存泄漏

JavaScript 是一種垃圾收集式語言,這就是說,內存是根據對象的創建分配給該對象的,并會在沒有對該對象的引用時由瀏覽器收回。JavaScript 的垃圾收集機制本身并沒有問題,但瀏覽器在為 DOM 對象分配和恢復內存的方式上卻有些出入。

InternetExplorer 和 Mozilla Firefox 均使用引用計數來為 DOM對象處理內存。在引用計數系統,每個所引用的對象都會保留一個計數,以獲悉有多少對象正在引用它。如果計數為零,該對象就會被銷毀,其占用的內存也會返回給堆。雖然這種解決方案總的來說還算有效,但在循環引用方面卻存在一些盲點。

循環引用的問題何在?

當兩個對象互相引用時,就構成了循環引用,其中每個對象的引用計數值都被賦1。在純垃圾收集系統中,循環引用問題不大:若涉及到的兩個對象中的一個對象被任何其他對象引用,那么這兩個對象都將被垃圾收集。而在引用計數系統,這兩個對象都不能被銷毀,原因是引用計數永遠不能為零。在同時使用了垃圾收集和引用計數的混合系統中,將會發生泄漏,因為系統不能正確識別循環引用。在這種情況下,DOM 對象和 JavaScript 對象均不能被銷毀。清單 1 顯示了在 JavaScript 對象和 DOM對象間存在的一個循環引用。


清單 1. 循環引用導致了內存泄漏
                            

	<html>
     	<body>
     	<script type="text/javascript">
     	document.write("circular references between JavaScript and DOM!");
     	var obj;
     	window.onload = function(){
		obj=document.getElementById("DivElement");
            	document.getElementById("DivElement").expandoProperty=obj;
            	obj.bigString=new Array(1000).join(new Array(2000).join("XXXXX"));
            	};
     	</script>
     	<div id="DivElement">Div Element</div>
     	</body>
     	</html>


          

如上述清單中所示,JavaScript 對象 obj 擁有到 DOM 對象的引用,表示為 DivElement 。而 DOM 對象則有到此 JavaScript 對象的引用,由 expandoProperty 表示??梢?,JavaScript 對象和 DOM 對象間就產生了一個循環引用。由于 DOM 對象是通過引用計數管理的,所以兩個對象將都不能銷毀。

另一種內存泄漏模式

在清單 2 中,通過調用外部函數 myFunction 創建循環引用。同樣,JavaScript 對象和 DOM 對象間的循環引用也會導致內存泄漏。


清單 2. 由外部函數調用引起的內存泄漏
                            

	<html>
	<head>
	<script type="text/javascript">
	document.write(" object s between JavaScript and DOM!");
	function myFunction(element)
	{
		this.elementReference = element;
		// This code forms a circular reference here
		//by DOM-->JS-->DOM
		element.expandoProperty = this;
	}
	function Leak() {
		//This code will leak
		
            
              
                new myFunction(document.getElementById("myDiv"));
              
            
            
	}
	</script>
	</head>
	<body onload="Leak()">
	<div id="myDiv"></div>
	</body>
	</html>


          

正如這兩個代碼示例所示,循環引用很容易創建。在 JavaScript 最為方便的編程結構之一:閉包中,循環引用尤其突出。




回頁首


JavaScript 中的閉包

JavaScript 的過人之處在于它允許函數嵌套。一個嵌套的內部函數可以繼承外部函數的參數和變量,并由該外部函數私有。清單 3 顯示了內部函數的一個示例。


清單 3. 一個內部函數
                            

	function parentFunction(paramA)
	{
    		var a = paramA;
    		function childFunction()
    		{
			return a + 2;
    		}
    		return childFunction();
	}


          

JavaScript 開發人員使用內部函數來在其他函數中集成小型的實用函數。如清單 3 所示,此內部函數 childFunction 可以訪問外部函數 parentFunction 的變量。當內部函數獲得和使用其外部函數的變量時,就稱其為一個 閉包 。

了解閉包

考慮如清單 4 所示的代碼片段。


清單 4. 一個簡單的閉包
                            

	<html>
	<body>
	<script type="text/javascript">
	document.write("Closure Demo!!");
	window.onload=
	function  closureDemoParentFunction(paramA)
	{
   		var a = paramA;
   		return function closureDemoInnerFunction (paramB)
   		{
     			alert( a +" "+ paramB);
   		};
	};
	var x = closureDemoParentFunction("outer x");
	x("inner x");
	</script>
	</body>
	</html>


          

在上述清單中, closureDemoInnerFunction 是在父函數 closureDemoParentFunction 中定義的內部函數。當用 外部的 x closureDemoParentFunction 進行調用時,外部函數變量 a 就會被賦值為 外部的 x 。函數會返回指向內部函數 closureDemoInnerFunction 的指針,該指針包括在變量 x 內。

外部函數 closureDemoParentFunction 的本地變量 a 即使在外部函數返回時仍會存在。這一點不同于 C/C++ 這樣的編程語言,在 C/C++ 中,一旦函數返回,本地變量也將不復存在。在 JavaScript 中,在調用 closureDemoParentFunction 的時候,帶有屬性 a 的范圍對象將會被創建。該屬性包括值 paramA ,又稱為 “外部 x” 。同樣地,當 closureDemoParentFunction 返回時,它將會返回內部函數 closureDemoInnerFunction ,該函數包括在變量 x 中。

由于內部函數持有到外部函數的變量的引用,所以這個帶屬性 a 的范圍對象將不會被垃圾收集。當對具有參數值 inner x x 進行調用時,即 x("inner x") ,將會彈出警告消息,表明 “ outer x innerx ”。

清單 4 簡要解釋了 JavaScript 閉包。閉包功能非常強大,原因是它們使內部函數在外部函數返回時也仍然可以保留對此外部函數的變量的訪問。不幸的是,閉包非常易于隱藏 JavaScript 對象 和 DOM 對象間的循環引用。




回頁首


閉包和循環引用

在清單 5 中,可以看到一個閉包,在此閉包內,JavaScript 對象( obj )包含到 DOM 對象的引用(通過 id "element" 被引用)。而 DOM 元素則擁有到 JavaScript obj 的引用。這樣建立起來的 JavaScript 對象和 DOM 對象間的循環引用將會導致內存泄漏。


清單 5. 由事件處理引起的內存泄漏模式
                            

	<html>
	<body>
	<script type="text/javascript">
	document.write("Program to illustrate memory leak via closure");
	window.onload=function outerFunction(){
		var obj = document.getElementById("element");
		obj.onclick=function innerFunction(){
		alert("Hi! I will leak");
		};
		obj.bigString=new Array(1000).join(new Array(2000).join("XXXXX"));
		// This is used to make the leak significant
	};
	</script>
	<button id="element">Click Me</button>
	</body>
	</html>


          




回頁首


避免內存泄漏

幸好,JavaScript 中的內存泄漏是可以避免的。當確定了可導致循環引用的模式之后,正如我們在上述章節中所做的那樣,您就可以開始著手應對這些模式了。這里,我們將以上述的 由事件處理引起的內存泄漏模式 為例來展示三種應對已知內存泄漏的方式。

一種應對 清單 5 中的內存泄漏的解決方案是讓此 JavaScript 對象 obj 為空,這會顯式地打破此循環引用,如清單 6 所示。


清單 6. 打破循環引用
                            

	<html>
	<body>
	<script type="text/javascript">
	document.write("Avoiding memory leak via closure by breaking the circular
    reference");
		window.onload=function outerFunction(){
		var obj = document.getElementById("element");
		obj.onclick=function innerFunction()
		{
			alert("Hi! I have avoided the leak");
			// Some logic here
		};
		obj.bigString=new Array(1000).join(new Array(2000).join("XXXXX"));
		
            
              
                obj = null
              
            
            ; //This breaks the circular reference
		};
	</script>
	<button id="element">"Click Here"</button>
	</body>
	</html>


          

清單 7 是通過添加另一個閉包來避免 JavaScript 對象和 DOM 對象間的循環引用。


清單 7. 添加另一個閉包
                            

	<html>
	<body>
	<script type="text/javascript">
	document.write("Avoiding a memory leak by adding another closure");
 	window.onload=function outerFunction(){
	var anotherObj = function innerFunction()
			 {
				// Some logic here
				alert("Hi! I have avoided the leak");
		  	 };
		 (function anotherInnerFunction(){
			var obj =  document.getElementById("element");
			obj.onclick=anotherObj })();
		    };
	</script>
	<button id="element">"Click Here"</button>
	</body>
	</html>


          

清單 8 則通過添加另一個函數來避免閉包本身,進而阻止了泄漏。


清單 8. 避免閉包自身
                            

	<html>
	<head>
	<script type="text/javascript">
	document.write("Avoid leaks by avoiding closures!");
	window.onload=function()
	{
		var obj = document.getElementById("element");
		obj.onclick = doesNotLeak;
	}
	
            
              
                function doesNotLeak()
              
            
            
	{
		//Your Logic here
		alert("Hi! I have avoided the leak");
	}

	</script>
	</head>
	<body>
	<button id="element">"Click Here"</button>
	</body>
	</html>


          




回頁首


結束語

本文解釋了循環引用是如何導致 JavaScript 中的內存泄漏的 —— 尤其是在結合了閉包的情況下。您還了解了涉及到循環引用的一些常見內存泄漏模式以及應對這些泄漏模式的幾種簡單方式。有關本文所討論的主題的更多信息,請參看 參考資料

JavaScript 中的內存泄露模式


更多文章、技術交流、商務合作、聯系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號聯系: 360901061

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對您有幫助就好】

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長會非常 感謝您的哦?。?!

發表我的評論
最新評論 總共0條評論
主站蜘蛛池模板: 一级做a| 国产欧美在线视频 | 九草视频在线 | 中文字字幕在线 | 午夜在线观看cao | 又黄又爽的网站 | 高清免费国产在线观看 | 亚洲av一级毛片特黄大片 | 91视频8mav| 国产一区二区三区久久久久久久久 | 一级毛片免费视频 | 免费观看一级特黄欧美大片 | 国产一区二区精品久久91 | 日本美女久久 | 欧美三级视频在线观看 | 国产精品免费一区二区三区都可以 | 成人app色深夜福利 欧美电影一区 | 国产精品视频 | 国产欧美成人 | 欧美国产高清 | 国产成人综合一区精品 | 国产成人亚洲综合a∨婷婷 91亚洲精品一区二区福利 | 午夜小视频免费观看 | 99亚洲精品 | 激情久久一区二区 | 天天色综合天天 | 九九视频网 | 欧美黑人狂野猛交老妇 | 日韩精品手机在线 | 欧美一区二区免费 | 欧美成人黑人视频免费观看 | 男女真实无遮挡xx00动态图120秒 | 日韩视频在线观看免费视频 | 日韩精品久久久久久久电影 | 国产精品国产精品国产专区不卡 | 亚洲欧美小视频 | 日韩国产欧美视频 | 欧美久草| 国产精品午夜小视频观看 | 九九久久看少妇高潮A片特黄 | 久久精品亚洲精品国产欧美kt∨ |