對JavaScript中閉包的理解

來源:互聯網
上載者:User

標籤:img   並且   頁面   標記   inf   效能   記憶體   函數   src   

相信很多人都有看過關於閉包的文章,但是真正意義上的瞭解清楚的也不多,今天我們就來談談對閉包的理解。

閉包在JavaScript中一直是一個很重要的存在,閉包很重要但是又很難理解,起初我也是這樣認為,但只要真的清楚之後,你會覺得很有趣。

 

我們先來看一個閉包的例子:

 

1 function foo() {2  let a = 2;3  function bar() {4   console.log(a);5  }6  return bar;7 }8 let baz = foo();9 baz();

 

大家肯定都寫過類似的代碼,相信很多小夥伴也知道這段代碼應用了閉包,但是,為什麼會產生閉包,閉包又是在哪裡?

回答上面的問題,首先必須Crowdsourced Security Testing道閉包是什麼,才能分析出閉包為什麼產生和閉包到底在哪?

當一個函數能夠記住並訪問到其所在的詞法範圍及範圍鏈,特彆強調是在其定義的範圍外進行的訪問,此時該函數和其上層執行內容共同構成閉包。

 

需要明確幾點:

  1、閉包一定是函數對象

  2、閉包和詞法範圍,範圍鏈,記憶體回收機制息息相關

  3、當函數一定是在其定義的範圍外進行的訪問時,才產生閉包

  4、閉包是由該函數和其上層執行內容共同構成

 

閉包是什麼,我們說清楚了,下面我們看下閉包是如何產生的。

 

現在我假設JS引擎執行到這行代碼:

 

let baz = foo();

  

此時,JS的範圍是這樣的:

 

 

這個時候foo函數已經執行完,JS的記憶體回收機制應該會自動將其標記為"離開環境",等待回收機制下次執行,將其記憶體進行釋放(標記清除)。

但是,我們仔細看圖中粉色的箭頭,我們將bar的引用指向baz,正是這種引用賦值,阻止了記憶體回收機制將foo進行回收,從而導致bar的整條範圍鏈都被儲存下來。

接下來,baz()執行,bar進入執行棧,閉包(foo)形成,此時bar中依舊可以訪問到其父範圍氣泡中的變數a。

 

這樣說可能不是很清晰,接下來我們藉助chrome的調試工具看下閉包產生的過程。

 

當JS引擎執行到這行代碼let baz = foo();時:

 

 

圖中所示,let baz = foo();已經執行完,即將執行baz();,此時Call Stack中只有全域上下文。

 

接下來baz();執行:

 

 

我們可以看到,此時bar進入Call Stack中,並且Closure(foo)形成。

 

針對上面我提到的幾點進行下說明:

  1、上述第二點(閉包和詞法範圍,範圍鏈,記憶體回收機制息息相關)大家應該都清楚了

  2、上述第三點,當函數baz執行時,閉包才產生

  3、上述第四點,閉包是foo,並不是bar,很多書(《you dont know JavaScript》《JavaScript進階程式設計》)中,都強調儲存下來的引用,即上例中的bar是閉包,而chrome認為被儲存下來的封閉空間foo是閉包

 

仔細想來,在我們範圍模型中,範圍鏈讓我們的內部bar氣泡能夠"看到"外面的世界,而閉包則讓我們的外部範圍能夠"關注到"內部的情況成為可能。可見,只要我們願意,內心世界和外面世界是可以相通的。

 

使用閉包時的注意事項:

閉包,在JS中絕對是一個高貴的存在,它讓很多不可能實現的代碼成為可能,但是物雖好,也要合理使用,不然不但不能達到我們想要的效果,有的時候可能還會適得其反。

 

記憶體流失(Memory Leak)

JavaScript分配給Web瀏覽器的可用記憶體數量通常比分配給傳統型應用程式的少,這樣做主要是防止JavaScript的網頁耗盡全部系統記憶體而導致系統崩潰。

因此,要想使頁面具有更好的效能,就必須確保頁面佔用最少的記憶體資源,也就是說,我們應該保證執行代碼只儲存有用的資料,一旦資料不再有用,我們就應該讓記憶體回收機制對其進行回收,釋放記憶體。 

我們現在都知道了閉包阻止了記憶體回收機制對變數進行回收,因此變數會永遠存在記憶體中,即使當變數不再被使用時,這樣會造成記憶體流失,會嚴重影響頁面的效能。因此當變數對象不再適用時,我們要將其釋放。

我們拿上面代碼舉例:

function foo() { let a = 2; function bar() {   console.log(a); } return bar;}let baz = foo();baz();//baz指向的對象會永遠存在堆記憶體中baz = null;//如果baz不在使用,將其指向的對象釋放

 

對JavaScript中閉包的理解

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.