摘要:前言之前發了一篇文章,寫了一些對于閉包的理解。現在補上閉包的應用篇,很慚愧因為嚴重的拖延癥一直拖到現在。本文主要分享一些常見的閉包用法和分析,也希望能增加對閉包的理解。
前言
之前發了一篇文章,寫了一些對于閉包的理解。現在補上閉包的應用篇,(很慚愧因為嚴重的拖延癥一直拖到現在)。本文主要分享一些常見的閉包用法和分析,也希望能增加對閉包的理解。
簡單回顧在之前的文章里,講解了閉包的原理,如果忘記了可以點擊這里再看一下,在這里我們簡單回顧一些知識點:
閉包的本質是一個函數
閉包可以訪問函數內部變量
閉包的存在會使內部變量保留在內存中
閉包的應用閉包常見的用法,就將圍繞這些特點展開:
1.模仿塊級作用域首先簡單舉個例子來,解釋一下什么是塊級作用域:
function A(num) { for (var i = 0; i < num; i++) { num++; } console.log(i) }
在這個簡單的函數中,變量i是在for循環中定義的,如果是在C++或者Java中,這樣定義的變量,一旦循環結束,變量也就隨之銷毀,i的作用范圍只在循環這個小塊,就稱為塊級作用域。在javascript中,沒有這樣的塊級作用域,前面一篇文章已經提到,變量是定義在函數的活動對象中的,因此,從定義i開始,在函數內部可以隨時訪問它。
這樣的壞處顯而易見:由于javascript不會告訴你變量是否已經被聲明,容易造成命名沖突,如果是在全局環境定義的變量,就會污染全局環境,因此可以利用閉包特性來模擬塊級作用域。不過在此之前要先介紹另一個知識點:匿名立即執行函數。如果已經比較熟悉的同學可以直接跳過這一塊:
首先舉個例子(我比較喜歡舉例,感覺看例子比較更容易理解):
var helloWorld = function(){ alert("Hello world") } helloWorld();//執行函數
上面的簡短代碼一共就做兩件事:1.定義了一個匿名函數并賦值給helloWorld;2.在helloWorld后面加括號表示調用函數,所以 匿名函數如果直接執行,是不是應該這樣寫:
function(){ alert("Hello world") }()
這樣的寫法會報錯,因為在javascript中,function是函數聲明的標志,不允許在后面直接加括號,而應該寫成這樣:
(function(){ //函數體 alert("Hello world") })()
也就是把聲明部分加括號即可,加了括號以后,這一段代碼就相當于執行了里面的函數體部分,但是此時內部的變量已經不能被外部訪問,請看下面詳細樣例
具體實現現在我們講模擬塊級作用域的具體步驟,假設還是針對前面的A函數,如果我們想讓i變量只有塊級作用域,可以這樣寫:
function A(num) { //核心代碼 (funnction(){ for(var i = 0; i注意看核心代碼部分,我們用剛剛講到的匿名自執行函數在內部形成了一個閉包,這個閉包在哪呢?一直強調,閉包的本質是函數,其實在這里閉包就是那個匿名函數,這個閉包可以到函數A內部的活動變量,又能保證自己內部的變量在自執行后直接銷毀,這個應該不難理解了
優點分析這種寫法的經常用在全局環境中,可以避免添加太多的全局變量和全局函數,特別是多人合作開發的時候,可以減少因此產生的命名沖突等,避免污染全局環境。
2.存儲變量我們知道閉包的另一個特點是可以保存外部函數的變量,原理是基于javascript中函數作用域鏈的特點,內部函數保留了對外部函數的活動變量的引用,所以變量不會被釋放(這一塊沒有理解清楚的請看前一篇文章,里面講的比較詳細),然后我們再來愉快地舉例子:
function B(){ var x = 100; return { function(){ return x } } } var m = B()//運行B函數,生成活動變量 x被m引用這是前文介紹過的一個最簡單的閉包例子,我們運行B函數,返回值就是B內部的匿名函數,此時m引用了變量x,所以B執行后x不會被釋放,利用這一點,我們可以把比較重要或者計算耗費很大的值存在x中,只需要第一次計算賦值后,就可以通過m函數引用x的值,不必重復計算,同時也不容易被修改
優點分析這種寫法可能會用在把一些不經常變動,但是計算比較復雜的值保存起來,就可以節省每次訪問的時間。
3.封裝私有變量javascript中沒有私有成員的概念,我們可以把函數當做一個范圍,函數內的變量就是私有變量,在外部無法引用,比如:
function C(a,b){ var c = a - b ; return c }在這個函數中,a b c都是私有變量,在外部無法訪,利用閉包的特點,我們可以就可以創建可以訪問私有變量的方法:
function Person(){ var name = "default"; this.getName:function(){ return name; } this,setName:function(value){ name = value; } } console.log(Person.getName())//default console.log(Person.setName("mike")) console.log(Person.getName())//mike在這個例子中,設置了兩個閉包函數來操作Person函數內部的name變量,除了這兩個函數,在外部無法再訪問到name變量,name也就相當于是私有成員。在這個例子中,我們用的是在構造函數中定義公有方法,對于所有的Person實例,都分別創建了新的辦法,當然還可以使用其他形式來避免這個問題,要涉及到創建對象模式的一些知識,在這里說明怕反而增加了閉包的理解難度,之后在寫對象和繼承的時候再提到(下一次更新一定不會這樣久了QAQ)。
小結關于閉包的主要主要應用就講到這里,本文中很多知識點與上一篇文章有關,又因為發布相隔時間比較長(我的鍋),建議大家可以先看看上一篇復習一下,這篇相對來前一篇容易理解,而且在舉例過程盡量沒有加入其它的疑難知識點,希望能對看到的人有所幫助。以上內容屬于個人見解,如果有不同意見,歡迎指出和探討。同時,碼字不易請尊重作者的版權,轉載請注明出處,如作商用,請與作者聯系,感謝!
補充如果看完對您有幫助,順手點個推薦唄~
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/86962.html
摘要:閉包的學術定義先來參考下各大權威對閉包的學術定義百科閉包,又稱詞法閉包或函數閉包,是引用了自由變量的函數。所以,有另一種說法認為閉包是由函數和與其相關的引用環境組合而成的實體。 前言 上一章講解了閉包的底層實現細節,我想大家對閉包的概念應該也有了個大概印象,但是真要用簡短的幾句話來說清楚,這還真不是件容易的事。這里我們就來總結提煉下閉包的概念,以應付那些非專人士的心血來潮。 閉包的學術...
摘要:引言滿滿的干貨,面試必系列,參考大量資料,并集合自己的理解以及相關的面試題,對核心知識點中的作用域閉包上下文進行了梳理。本篇重點介紹閉包和。所以,有另一種說法認為閉包是由函數和與其相關的引用環境組合而成的實體。 showImg(https://segmentfault.com/img/bVbo4hv?w=1800&h=1000); 引言 滿滿的干貨,面試必bei系列,參考大量資料,并集...
摘要:一般來講,函數執行完畢后,局部活動對象就會被銷毀,內存中僅保存全局作用域,但是閉包的情況有所不同理解閉包的前提先理解另外兩個內容作用域鏈垃圾回收作用域鏈當代碼在執行過程中,會創建變量對象的一個作用域鏈。 閉包是javascript語言的一個難點,也是它的特色,很多高級應用都要依靠閉包來實現。個人的理解是:函數中嵌套函數。 閉包的定義及其優缺點 閉包是指有權訪問另一個函數作用域中的變量的...
閱讀 3455·2019-08-30 10:54
閱讀 3154·2019-08-29 16:38
閱讀 2175·2019-08-26 14:06
閱讀 1517·2019-08-23 15:39
閱讀 3041·2019-08-23 15:37
閱讀 2887·2019-08-23 13:50
閱讀 3194·2019-08-22 17:14
閱讀 2381·2019-08-22 15:44