《JavaScript權威指南》學習——js閉包

來源:互聯網
上載者:User

標籤:函數   bsp   glob   http   logs   屌絲   語言   推薦   記憶體   

序:閉包這個玩意啊~在很多沒有代碼塊的語言中都會出現,已經成為大多程式員入門的一道坎,閉包讓很多程式員覺得晦澀(事實上百度一下這個名詞,真的說的很晦澀啊親==|||),本座第一次知道閉包這個名詞是從《JavaScript權威指南》中讀到的,當時還是2015年的3月份,我剛開始看寒假購買的書,話說那時我還沒有和初戀分手,我清楚的記得我在從徐州回蘇州的火車上全程研究這本《JavaScript權威指南》的屌絲情境(異地戀),前女友說這本書封面上的犀牛醜死了,我說“你懂啥!”==|||

話不多說,經過一番回憶,我想起來閉包這個東西直到分手後的5個月裡都沒有搞清楚,直到某一天我在實驗室寫完了三段js代碼對比後,我了悟了這本神書的講的閉包思想!

先來看下閉包的百度百科,且看(配圖):

 

閉包是可以包含自由(未綁定到特定對象)變數的代碼塊;這些變數不是在這個代碼塊內或者任何全域上下文中定義的,而是在定義代碼塊的環境中定義(局部變數)。“閉包” 一詞來源於以下兩者的結合:要執行的代碼塊(由於自由變數被包含在代碼塊中,這些自由變數以及它們引用的對象沒有被釋放)和為自由變數提供綁定的計算環境(範圍)。

在 Scala、Scheme、Common Lisp、Smalltalk、Groovy、JavaScript、Ruby、 Python、Go、Lua、objective c、swift 以及Java(Java8及以上)等語言中都能找到對閉包不同程度的支援。

 

乍一看,百度說的神乎其神,什麼代碼塊,什麼局部變數,說白了,我們只要搞清js的代碼的一點原理:範圍的釋放和存在問題。

閉包(closure)是Javascript語言的一個痛點,也是它的特色,很多進階應用程式都要依靠閉包實現。

閉包有三個特性:

1.函數嵌套函數

2.函數內部可以引用外部的參數和變數

3.參數和變數不會被記憶體回收機制回收

 

對比下面三段代碼:

且看看下面代碼:

//全域變數的應用和變化Var GLOBAL = 1          //全域變數function change_global(){    var GLOBAL = 2;             //重新定義了GLOBAL作為局部變數,不加var則變成了引用全域變數    alert(GLOBAL);}change_global();Alert(GLOBAL);

 

瀏覽器顯示:先2,後1。

結論:驗證了一點,函數改變了局部變數,但沒有改變全域變數,但是一旦去掉了局部變數GLOBAL前面的var那麼結果就是2,2。函數執行完後,函數的範圍鏈被銷毀,隨之局部變數被銷毀了!全域變數要等到頁面關閉(程式結束)被銷毀

如果很熟悉js文法和範圍鏈的,可以跳過上面的代碼,我是為了說下面的代碼!

且看下面代碼:

//z是個普通的function,執行一次範圍鏈就被銷毀var function z(t){    var s=[1,2,3];              //局部變數s    s.push(t);          //往s數組中添加數字    return s;}z(4);   //執行後銷毀這次z(5);   //執行後銷毀這次alert(z(6));    //執行後銷毀這次

 

瀏覽器顯示:1,2,3,6。

結論:4,5呢?當然是因為前兩次執行結束後函數被銷毀了,所以最後只有6被添加進去了,充分證明了js執行函數在記憶體中的原理——執行完就銷毀function中的一切!

上面的話不完全對,真的是一切嗎?

且看下面代碼:

//x這是個閉包函數,結束後會被銷毀,但是因為他返回了另一個函數,這個函數調用並返回了局部變數s,所以s不能被摧毀了,必須被保留下來!//x這是個閉包函數,結束後會被銷毀,但是因為他返回了另一個函數,這個函數調用並返回了局部變數s,所以s不能被摧毀了,必須被保留下來!function x(){    var s=[1,2,3];              //一樣的局部變數s    return function(t){        s.push(t);      //一樣往s中添加數字        return s;    };}var y=x();      //閉包賦值給y變數y(4);y(5);alert(y(6));

 

瀏覽器顯示:1,2,3,4,5,6。

結論:function x()事實上是製作了一個只屬於代碼塊環境的閉包,閉包中的s變數是不會因為這個x執行完成後被銷毀,也不會因為返回的函數執行完後被銷毀,即使這段代碼全部執行完,s仍然保留在記憶體中,範圍鏈也仍然存在,知道程式結束(關閉瀏覽器)!所以注意:濫用閉包會導致記憶體不足的!

為了更好的說明,銷毀與不銷毀的問題,我推薦下面這段代碼

//全域對象y,當中的變數:程式結束前永遠不會銷毀//函數中的局部對象在函數結束後也會像變數一樣被銷毀的var y={    s:[1,2,3],          //對象中的變數    //對象中的方法(類似於函數)add:function(t){        this.s.push(t);        return this.s;    }}y.add(4);y.add(5);alert(y.s);

 

瀏覽器顯示:1,2,3,4,5,6。

結論:用對象和閉包達到同樣的效果,因為對象除非指定銷毀,不然會存留在當前程式記憶體中!

使用閉包有一個優點,也是它的缺點,就是可以把局部變數駐留在記憶體中,可以避免使用全域變數。全域變數在每個模組都可調用,這勢必將是災難性的。

 

《JavaScript權威指南》學習——js閉包

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.