<font id="zqva1"></font>
<rt id="zqva1"></rt>
  • <tt id="zqva1"></tt>
    <cite id="zqva1"></cite>

    <cite id="zqva1"><noscript id="zqva1"></noscript></cite>
      <rp id="zqva1"><meter id="zqva1"></meter></rp>

        <cite id="zqva1"></cite>
          <b id="zqva1"></b>
          <rp id="zqva1"></rp>
          <cite id="zqva1"></cite>

          <rt id="zqva1"></rt>

        1. <rp id="zqva1"></rp>

          js常見的內存泄漏及解決方法總匯

          時間:?2017-12-06閱讀:?6235標簽:?內存

          什么是內存泄漏?

          內存泄漏指由于疏忽或錯誤造成程序未能釋放已經不再使用的內存。內存泄漏并非指內存在物理上的消失,而是應用程序分配某段內存后,由于設計錯誤,導致在釋放該段內存之前就失去了對該段內存的控制,從而造成了內存的浪費。

          內存泄漏通常情況下只能由獲得程序源代碼的程序員才能分析出來。然而,有不少人習慣于把任何不需要的內存使用的增加描述為內存泄漏,即使嚴格意義上來說這是不準確的。


          JS垃圾收集機制:

          js具有自動回收垃圾的機制,即執行環境會負責管理程序執行中使用的內存。在C和C++等其他語言中,開發者的需要手動跟蹤管理內存的使用情況。在編寫js代碼時候,開發人員不用再關心內存使用的問題,所需內存的分配 以及無用的回收完全實現了自動管理。

          Js中最常用的垃圾收集方式是標記清除(mark-and-sweep)。當變量進入環境(例如,在函數中聲明一個變量)時,就將這個變量標記為“進入環境”。從邏輯上講,永遠不能釋放進入環境的變量所占的內存,因為只要執行流進入相應的環境,就可能用到它們。而當變量離開環境時,這將其 標記為“離開環境”。


          這篇文章主要講解JavaScript常見的內存泄漏及解決辦法!


          1.意外的全局變量:

          Js處理未定義變量的方式比較寬松:未定義的變量會在全局對象創建一個新變量。在瀏覽器中,全局對象是window。

          function foo(arg) { 
              bar = "this is a hidden global variable"; //等同于window.bar="this is a hidden global variable"
              this.bar2= "potential accidental global";//這里的this 指向了全局對象(window),等同于window.bar2="potential accidental global"
          }

          解決方法:在JavaScript程序中添加,開啟嚴格模式'use strict',可以有效地避免上述問題。

          注意:那些用來臨時存儲大量數據的全局變量,確保在處理完這些數據后將其設置為null或重新賦值。與全局變量相關的增加內存消耗的一個主因是緩存。緩存數據是為了重用,緩存必須有一個大小上限才有用。高內存消耗導致緩存突破上限,因為緩 存內容無法被回收。


          2.循環引用

          在js的內存管理環境中,對象 A 如果有訪問對象 B 的權限,叫做對象 A 引用對象 B。引用計數的策略是將“對象是否不再需要”簡化成“對象有沒有其他對象引用到它”,如果沒有對象引用這個對象,那么這個對象將會被回收 。

          let obj1 = { a: 1 }; // 一個對象(稱之為 A)被創建,賦值給 obj1,A 的引用個數為 1   
          let obj2 = obj1; // A 的引用個數變為 2  
            
          obj1 = 0; // A 的引用個數變為 1  
          obj2 = 0; // A 的引用個數變為 0,此時對象 A 就可以被垃圾回收了

          但是引用計數有個最大的問題: 循環引用。 

          function func() {  
              let obj1 = {};  
              let obj2 = {};  
            
              obj1.a = obj2; // obj1 引用 obj2  
              obj2.a = obj1; // obj2 引用 obj1  
          }

          當函數 func 執行結束后,返回值為 undefined,所以整個函數以及內部的變量都應該被回收,但根據引用計數方法,obj1 和 obj2 的引用次數都不為 0,所以他們不會被回收。要解決循環引用的問題,最好是在不使用它們的時候手工將它們設為空。上面的例子可以這么做:

          obj1 = null;  
          obj2 = null;


          3.被遺忘的計時器和回調函數

          let someResource = getData();  
          setInterval(() => {  
              const node = document.getElementById('Node');  
              if(node) {  
                  node.innerHTML = JSON.stringify(someResource));  
              }  
          }, 1000);

          上面的例子中,我們每隔一秒就將得到的數據放入到文檔節點中去。但在 setInterval 沒有結束前,回調函數里的變量以及回調函數本身都無法被回收。那什么才叫結束呢?就是調用了 clearInterval。如果回調函數內沒有做什么事情,并且也沒有被 clear 掉的話,就會造成內存泄漏。不僅如此,如果回調函數沒有被回收,那么回調函數內依賴的變量也沒法被回收。上面的例子中,someResource 就沒法被回收。同樣的,setTiemout 也會有同樣的問題。所以,當不需要 interval 或者 timeout 時,最好調用 clearInterval 或者 clearTimeout。  


          4.DOM泄漏

          在Js中對DOM操作是非常耗時的。因為JavaScript/ECMAScript引擎獨立于渲染引擎,而DOM是位于渲染引擎,相互訪問需要消耗一定的資源。  而IE的DOM回收機制便是采用引用計數的,以下主要針對IE而言的。

          a.沒有清理的DOM元素引用

          var refA = document.getElementById('refA');
          document.body.removeChild(refA);
           // #refA不能回收,因為存在變量refA對它的引用。將其對#refA引用釋放,但還是無法回收#refA。

          解決辦法:refA = null;


          b.給DOM對象添加的屬性是一個對象的引用:

          var MyObject = {}; 
          document.getElementById('myDiv').myProp = MyObject;

          解決方法: 
          在window.onunload事件中寫上: document.getElementById('myDiv').myProp = null;  


          c.DOM對象與JS對象相互引用:

          function Encapsulator(element) { 
          this.elementReference = element; 
          element.myProp = this; 
          } 
          new Encapsulator(document.getElementById('myDiv'));

          解決方法: 在onunload事件中寫上: document.getElementById('myDiv').myProp = null;   


          d.給DOM對象用attachEvent綁定事件:

          function doClick() {} 
          element.attachEvent("onclick", doClick);

          解決方法: 在onunload事件中寫上: element.detachEvent('onclick', doClick);   

            

          e.從外到內執行appendChild。這時即使調用removeChild也無法釋放:

          var parentDiv = document.createElement("div"); 
          var childDiv = document.createElement("div"); 
          document.body.appendChild(parentDiv); 
          parentDiv.appendChild(childDiv);

          解決方法: 從內到外執行appendChild:   

          var parentDiv = document.createElement("div"); 
          var childDiv = document.createElement("div"); 
          parentDiv.appendChild(childDiv); 
          document.body.appendChild(parentDiv);


          5.js的閉包

          閉包在IE6下會造成內存泄漏,但是現在已經無須考慮了。值得注意的是閉包本身不會造成內存泄漏,但閉包過多很容易導致內存泄漏。閉包會造成對象引用的生命周期脫離當前函數的上下文,如果閉包如果使用不當,可以導致環形引用(circular reference),類似于死鎖,只能避免,無法發生之后解決,即使有垃圾回收也還是會內存泄露。  


          6.console

          控制臺日志記錄對總體內存配置文件的影響可能是許多開發人員都未想到的極其重大的問題。記錄錯誤的對象可以將大量數據保留在內存中。注意,這也適用于: 

          1)、 在用戶鍵入 JavaScript 時,在控制臺中的一個交互式會話期間記錄的對象。

          2)、由 console.log 和 console.dir 方法記錄的對象。 


          結束語

          本文主要介紹了幾種常見的內存泄露。在開發過程,需要我們特別留意,隨著瀏覽器的升級,目前大部分 大部分瀏覽器都已改進了內存清理功能。

          站長推薦

          1.阿里云: 本站目前使用的是阿里云主機,安全/可靠/穩定。點擊領取2000元代金券、了解最新阿里云產品的各種優惠活動點擊進入

          2.騰訊云: 提供云服務器、云數據庫、云存儲、視頻與CDN、域名等服務。騰訊云各類產品的最新活動,優惠券領取點擊進入

          3.廣告聯盟: 整理了目前主流的廣告聯盟平臺,如果你有流量,可以作為參考選擇適合你的平臺點擊進入

          鏈接: http://www.modern-decoration.com.cn/article/detial/225

          通過內存分析來解釋JavaScript數組賦值問題

          初始的內存分布,形參變量存在棧中,對象存在堆內。如圖,棧中有arr,arr0,還有fun的形參data三個變量,分別指向了堆中的兩個數組對象的首地址。

          Node.js 中內存泄漏分析

          內存泄漏(Memory Leak)指由于疏忽或錯誤造成程序未能釋放已經不再使用的內存的情況。如果內存泄漏的位置比較關鍵,那么隨著處理的進行可能持有越來越多的無用內存,這些無用的內存變多會引起服務器響應速度變慢

          JavaScript中的垃圾回收和內存泄漏

          程序的運行需要內存。只要程序提出要求,操作系統或者運行時就必須供給內存。所謂的內存泄漏簡單來說是不再用到的內存,沒有及時釋放。為了更好避免內存泄漏,我們先介紹Javascript垃圾回收機制。

          怎樣修復Web應用程序中的內存泄漏?

          從服務器端渲染的網站切換到客戶端渲染的 SPA 時,我們突然不得不更加注意用戶設備上的資源,必須做很多工作:不要阻塞 UI 線程,不要使筆記本電腦的風扇瘋狂旋轉,不要耗盡手機的電池等。我們將交互性和“類應用程序”行為轉換成了更好的新型問題

          為什么要內存對齊

          CPU訪問內存時,并不是逐個字節訪問,而是以字長(word size)為單位訪問。比如32位的CPU,字長為4字節,那么CPU訪問內存的單位也是4字節

          JavaScript內存管理

          高級語言解釋器嵌入了“垃圾回收器”,監控著所有對象,當對象生存周期結束時會將其刪除。內嵌的垃圾回收器的問題:自動尋找是否一些內存“不再需要”的問題是無法判定的

          JavaScript的內存模型

          在我們的前端日常工作中,無時無刻不在進行著變量的聲明和賦值,你是否也曾碰到過變量聲明報錯或變量被污染的問題,如果你跟筆者一樣碰到過,那么我們應該暫時停下來好好思考問題發生的原因以及如何采取相應的補救措施

          Node.js的內存分配和垃圾回收

          Node.js是一個由JavaScript V8引擎控制的C++程序,V8的內存管理模式一個運行的程序通常是通過在內存中分配一部分空間來表示的。這部分空間被稱為駐留集(Resident Set)。

          Js內存泄露

          用戶一般不會在一個 Web 頁面停留比較久,即使有一點內存泄漏,重載頁面內存也會跟著釋放。而且瀏覽器也有自動回收內存的機制,所以我們前端其實并沒有像 C、C++ 這類語言一樣,特別關注內存泄漏的問題。

          JS內存管理

          像C語言這樣的底層語言一般都有底層的內存管理接口,比如 malloc()和free()。相反,JavaScript是在創建變量(對象,字符串等)時自動進行了分配內存,并且在不使用它們時“自動”釋放。 釋放的過程稱為垃圾回收。這個“自動”是混亂的根源

          內容以共享、參考、研究為目的,不存在任何商業目的。其版權屬原作者所有,如有侵權或違規,請與小編聯系!情況屬實本人將予以刪除!

          文章投稿關于web前端網站點搜索站長推薦網站地圖站長QQ:522607023

          小程序專欄: 土味情話心理測試腦筋急轉彎幽默笑話段子句子語錄成語大全運營推廣

          国产精品高清视频免费 - 视频 - 在线观看 - 影视资讯 - 唯爱网