<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      JavaScript 中的內存泄露模式【轉】

        在博問中看到一個問題(為什么說這段JavaScript代碼存在循環引用)中有一篇好文章,特轉過來學習下。

        原文地址:JavaScript 中的內存泄露模式

        本文地址:JavaScript 中的內存泄露模式【轉】

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

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

      JavaScript 中的內存泄漏

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

        Internet Explorer 和 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 中定義的內部函數。當用外部的 xclosureDemoParentFunction 進行調用時,外部函數變量 a 就會被賦值為外部的 x。函數會返回指向內部函數 closureDemoInnerFunction 的指針,該指針包括在變量 x 內。

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

        由于內部函數持有到外部函數的變量的引用,所以這個帶屬性 a 的范圍對象將不會被垃圾收集。當對具有參數值 inner xx 進行調用時,即 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 中的內存泄漏的 —— 尤其是在結合了閉包的情況下。您還了解了涉及到循環引用的一些常見內存泄漏模式以及應對這些泄漏模式的幾種簡單方式。有關本文所討論的主題的更多信息,請參看 參考資料。

      posted @ 2012-03-13 16:29  artwl  閱讀(948)  評論(0)    收藏  舉報

      個人簡介

      var ME = {
      	"name": "土豆/Artwl",
      	"job": "coding",
      	"languages": [
      		"JS", "HTML",
                      "CSS", "jQuery"
      		"MVC",".NET",
      		"設計模式"
      	],
      	"hobby": [
      		"閱讀", "旅游",
      		"音樂", "電影"
      	]
      }
      
      TOP
      主站蜘蛛池模板: 亚洲AV无码专区亚洲AV桃| 好男人社区神马在线观看www| 91中文字幕一区在线| 国产一区精品综亚洲av| 国产香蕉尹人综合在线观看| 日韩av片无码一区二区不卡| 欧洲亚洲精品免费二区| 2021亚洲va在线va天堂va国产| 狠狠色噜噜狠狠狠狠色综合久av| 2020国产成人精品视频| 综合区一区二区三区狠狠| 赤城县| 国产va免费精品观看精品| 国产成人无码免费看片软件| 国产成人午夜福利在线观看| 亚洲欧美在线观看品| 国产欧美日韩视频一区二区三区| 国产av一区二区三区精品| 欧美日韩v| 动漫AV纯肉无码AV电影网| 中文字幕亚洲精品第一页| 久久人妻公开中文字幕| 色爱综合另类图片av| 精品久久精品久久精品九九| 国产一区二区三区在线观看免费| 久久99精品久久久久久| 日韩精品不卡一区二区三区| 亚洲国产精品日韩在线| 久久人人爽人人爽人人av| 白丝乳交内射一二三区| 久久亚洲精品亚洲人av| 久久人妻无码一区二区三区av| 99久热在线精品视频| 91中文字幕一区在线| 天天做天天躁天天躁| 成人国产精品日本在线观看| 久久精品一本到99热免费| 亚洲爆乳WWW无码专区| 亚洲午夜福利精品无码不卡| 欧洲精品亚洲精品日韩专区| 成年午夜性影院|