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