【前端--JavaScript】知識點(五)—— 項目中的內存泄漏(一)

這是我參與8月更文挑戰的第5天,活動詳情查看:8月更文挑戰**node

最近在寫小程序的過程當中,用到了不少的console.log,開始是爲了聯調方便,一直沒有刪除,致使頁面時不時有卡頓現象出現,開始以爲頁面從新刷新就行了,可是產品和測試不會答應的呀,後來排查了一下問題,才發現頁面中出現不少種內存泄漏,想起以前面試時候這個問題也是考了不少次,一直沒有總結,今天就趁機總結一下也好提醒本身平時多多注意。面試

什麼是內存泄漏?

首先咱們得清楚什麼是內存泄漏,在引擎中有垃圾回收機制,主要針對一些程序中再也不使用的對象,清理回收釋放掉內存,可是實際上垃圾回收機制並不會把再也不使用的對象所有回收掉。所以咱們在代碼中要主動避免一些不利於引擎作垃圾回收的操做,這些沒有被及時回收的對象內存,咱們叫它內存泄漏(Memory Leak)小程序

常見的內存泄漏

來看看一些常見的內存泄漏案例:瀏覽器

不正當的閉包

大部分認爲閉包就是函數內部嵌套並return一個函數,我翻了翻幾本書中的描述:markdown

  • JavaScript高級程序設計:閉包是指有權訪問另外一個函數做用域中的變量的函數。
  • JavaScript權威指南:從技術的角度講,全部的JavaScript函數都是閉包,他們都是對象,都關聯到做用域鏈。
  • 你不知道的JavaScript:當函數能夠記住並訪問所在的詞法做用域時,就產生了閉包,即便函數是在當前詞法做用域以外執行。

閉包涉及的範圍是比較廣了,如今看一個廣泛的例子再認識一下閉包:閉包

function fnOne(){
  let test = new Array(1000).fill('www')
  return function(){
    console.log('hahaha')
  }
}
let fn1Child = fnOne()
fn1Child()
複製代碼

這裏由於return的函數中存在函數fnOne中的test變量引用,test不會被回收,也就形成了內存泄漏。app

怎麼解決呢?就是在函數調用後,把外部的引用關係置空就行了:函數

function fnOne(){
  let test = new Array(1000).fill('www')
  return function(){
   console.log(test)
   return test
  }
}
let fn1Child = fnOne();
fn1Child()
fn1Child = null;
複製代碼

減小使用閉包,不正當的使用閉包可能會形成內存泄漏。post

隱式全局變量

在JavaScript中,垃圾回收是自動執行的,可是對於全局變量,垃圾回收器很難判斷這些變量何時纔不被須要,因此全局變量不會被回收,這時候就產生了內存泄漏:測試

function fn(){
  // 沒有聲明從而製造了隱式全局變量test1
  test1 = new Array(1000).fill('isboyjc1')
  
  // 函數內部this指向window,製造了隱式全局變量test2
  this.test2 = new Array(1000).fill('isboyjc2')
}
fn()
複製代碼

遺忘的定時器

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

代碼中,每隔一秒就把獲得的數據放入到node節點中,可是在setInterval沒有結束以前,回調函數裏的變量以及回調函數自己都沒法被回收。這時候須要用到clearInterval來清理這個定時器,才能回收someResource

setTiemout也是一樣的道理,不須要時候,及時去清除。

遺忘的事件監聽器

在代碼中咱們會用到事件監聽器,在組件內掛載相關的函數,組件銷燬時候不主動清除時,其中的變量和函數會被認爲是須要的,就不會被回收,這些內部引用的變量存儲了大量數據,就會引發頁面佔用內存太高,形成內存泄漏。

遺忘的監聽者模式

不論是Vue仍是React,監聽者模式實現一些消息通訊是 很廣泛的,好比EventBus,當咱們實現了監聽者模式在組件內掛載相關的函數,組件銷燬時候不主動清除,就一樣不會進行回收。這時候咱們要在beforeDestroy 組件銷燬生命週期裏及時去清除。

未清理的Console輸出

最後就是咱們在聯調時候常見的console.log了,咱們在瀏覽器控制檯能夠看到數據輸出,輸出對象的時候就也形成了內存泄漏。

差很少說完了常見的內存泄漏,下一篇就講一下怎麼排查定位代碼中是否存在內存泄漏

相關文章
相關標籤/搜索