摘要:閉包是什么這是一個(gè)在面試的過(guò)程中出現(xiàn)的概率為以上的問(wèn)題,也是我們張口就來(lái)的問(wèn)題。文章推薦我們面試中在被問(wèn)到閉包這個(gè)問(wèn)題是要注意的幾點(diǎn)閉包的延伸,讓面試變得
閉包是什么?這是一個(gè)在面試的過(guò)程中出現(xiàn)的概率為60%以上的問(wèn)題,也是我們張口就來(lái)的問(wèn)題。但是我們往往發(fā)現(xiàn),在面試的過(guò)程中我們的回答并不那么讓面試官滿意,我們雖然能張口說(shuō)出一些但是卻不能系統(tǒng)的對(duì)這個(gè)問(wèn)題進(jìn)行回答。面試官希望加入自己團(tuán)隊(duì)的是一個(gè)基礎(chǔ)扎實(shí),條理清晰,舉一反三,吃苦耐勞的人,如果我們?cè)诿嬖囍械幕卮鹬皇恰畺|一榔頭,西一棒槌’,結(jié)果我想已經(jīng)顯而易見(jiàn)了。
接下來(lái)將從三個(gè)方面來(lái)說(shuō)閉包:
1.閉包是什么?
2.為什么要用閉包?
3.如何使用閉包?
閉包是什么定義
閉包就是外層函數(shù)的內(nèi)部函數(shù)(不過(guò)要注意它的特性)。
特性
1.它有自己的局部作用域(local scope);
2.它可以訪問(wèn)外部函數(shù)的作用域(outer scope),參數(shù)(parameters),而不是參數(shù)對(duì)象;
3.它也可以訪問(wèn)全局的(global scope)
4.參數(shù)和變量不會(huì)被垃圾回收機(jī)制回收(不當(dāng)?shù)氖褂瞄]包可能造成內(nèi)存泄漏的原因)
閉包與作用域javascript的作用域
javascript 是一個(gè)函數(shù)級(jí)的作用域(function-level scope),而不是一個(gè)像其他語(yǔ)言一樣的塊級(jí)作用域(block-level-scope);此外javascript是一個(gè)異步的事件驅(qū)動(dòng)語(yǔ)言(javascript是單線程的語(yǔ)言),想要了解更多的異步事件驅(qū)動(dòng)我們可以看一下node.js的
閉包工作原理
1.閉包存儲(chǔ)外部函數(shù)變量的引用,因此總是可以訪問(wèn)外部變量的更新值
2.在它的外部函數(shù)被執(zhí)行并返回值后,閉包仍然可以執(zhí)行(常駐內(nèi)存)
為什么要用閉包例如:在for循環(huán)中我們?cè)L問(wèn)一個(gè)變化的變量時(shí)存在問(wèn)題
而我們根據(jù)閉包的特性和工作原理可以很好的解決這個(gè)問(wèn)題
閉包的好處
1.保存狀態(tài)(使一個(gè)變量長(zhǎng)期駐扎在內(nèi)存中)
2.避免全局變量的污染
3.允許私有成員的存在
如何使用閉包通常在函數(shù)返回時(shí)會(huì)失去對(duì)變量的訪問(wèn)權(quán)限,如下面的示例:
function unClosure() { var innerVar = "I"m inner-variable"; return innerVar; } unClosure(); // returns "I"m inner-variable"
上面的示例代碼沒(méi)有多少的實(shí)際意義,我們做一下修改,如下:
function unClosure(outerVar) { return outerVar; } unClosure(); unClosure("apple"); // return "apple"; unClosure("banana"); // return "banana"; unClosure("tomato"); // return "tomato";
但是我們發(fā)現(xiàn),在unClosure運(yùn)行之后,我們將沒(méi)有辦法去獲得outerVar。當(dāng)然,我們可以再一次運(yùn)行unClosure一次又一次,但是每一次調(diào)用之后將會(huì)創(chuàng)造一個(gè)新的outerVar,這樣很難保證每一個(gè)outerVar是最新的,因?yàn)楫?dāng)前的調(diào)用沒(méi)有存儲(chǔ)任何引用。所以,我們可以將代碼修改如下:
function aClosure() { var longLivedVariable = "I"m here for a long time"; var innerFunction = function inner() { return longLivedVariable; } return innerFunction; } var closure = aClosure(); // 返回一個(gè)innerFunction的引用 closure(); // returns "I"m here for a long time"
我們發(fā)現(xiàn)aClosure沒(méi)有返回longLivedVariable,而是返回innerFunction的引用。這也即是說(shuō)有一個(gè)引用一直掛載在innerFunction上,由于innerFunction上有一個(gè)longLivedVariable的引用,那么變量將一直存在。為了說(shuō)明以上的推論,我們將代碼修改如下:
function aClosure(longLivedVariable) { var innerFunction = function inner() { return longLivedVariable; } return innerFunction; } var closure = aClosure("apple"); // 返回一個(gè)innerFunction的引用 closure(); // returns "apple" closure(); // returns "apple" closure(); // returns "apple" var closure2 = aClosure("banana"); // 返回一個(gè)innerFunction的引用 closure2(); // returns "banana" closure2(); // returns "banana" closure2(); // returns "banana"
當(dāng)我們釣友closure(),我們一直調(diào)用的是innerFunction(),或者說(shuō)是aClosure()的返回值,而對(duì)于innerFunction來(lái)說(shuō)返回的是longLivedVariable.
上面的例子是保存狀態(tài)的簡(jiǎn)單使用,下面我們來(lái)一個(gè)保存狀態(tài)和允許擁有私有成員的例子,
這個(gè)常見(jiàn)的就是對(duì)象。示例代碼如下:
function person(name) { return { getName: function() { return name; } } } var person = person("lisi"); person.name // returns undefined person.getName() // returns "lisi" var person2 = cat("張華"); person2.getName() // returns "張華"
這里的name即是私有成員,通過(guò)person,和person2兩個(gè)對(duì)象實(shí)例說(shuō)明可以保存狀態(tài)
從上面兩個(gè)例子我們也可以看出閉包的另一個(gè)好處,通過(guò)保存狀態(tài)或?qū)⒍x私有成員,可以實(shí)現(xiàn)避免全局變量污染的好處。
我們知道在javascript中避免全局變量污染的一般方法:
1.定義全局命名空間
2.使用一個(gè)立即執(zhí)行函數(shù)
githubGist的代碼實(shí)例參考
stackflow的優(yōu)秀解答
閉包與立即執(zhí)行函數(shù)閉包幫我們解決了我們要全局的使用,又不想全局所帶來(lái)的污染的問(wèn)題,使用閉包你可以像工廠方法一樣創(chuàng)建多個(gè)不同的對(duì)象。但在實(shí)際的開(kāi)發(fā)過(guò)程中我們又會(huì)遇到這樣的問(wèn)題,希望對(duì)象只有一份,也就是我們常說(shuō)的單例模式,在javascript中函數(shù)沒(méi)法私有化,所以轉(zhuǎn)個(gè)思路我們可以讓這個(gè)工廠方法不能多次調(diào)用,而這樣的函數(shù)就是匿名函數(shù);而且只能調(diào)用一次,就是在聲明函數(shù)的時(shí)候立即執(zhí)行。
文章推薦lucy’s blog about closure
by rlynjb about closure
我們面試中在被問(wèn)到閉包這個(gè)問(wèn)題是要注意的幾點(diǎn)
閉包的延伸,讓面試變得so easy
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://m.hztianpu.com/yun/90389.html
摘要:同行這么做使用實(shí)現(xiàn)圓形進(jìn)度條前端掘金在開(kāi)發(fā)微信小程序的時(shí)候,遇到圓形進(jìn)度條的需求。實(shí)現(xiàn)也談數(shù)組去重前端掘金的數(shù)組去重是一個(gè)老生常談的話題了。百度前端技術(shù)學(xué)院自定義前端掘金一標(biāo)簽概念元素表示用戶界面中項(xiàng)目的標(biāo)題。 閑話圖片上傳 - 掘金作者:孫輝,美團(tuán)金融前端團(tuán)隊(duì)成員。15年畢業(yè)加入美團(tuán),相信技術(shù),更相信技術(shù)只是大千世界里知識(shí)的一種,個(gè)人博客: https://sunyuhui.com ...
摘要:同行這么做使用實(shí)現(xiàn)圓形進(jìn)度條前端掘金在開(kāi)發(fā)微信小程序的時(shí)候,遇到圓形進(jìn)度條的需求。實(shí)現(xiàn)也談數(shù)組去重前端掘金的數(shù)組去重是一個(gè)老生常談的話題了。百度前端技術(shù)學(xué)院自定義前端掘金一標(biāo)簽概念元素表示用戶界面中項(xiàng)目的標(biāo)題。 閑話圖片上傳 - 掘金作者:孫輝,美團(tuán)金融前端團(tuán)隊(duì)成員。15年畢業(yè)加入美團(tuán),相信技術(shù),更相信技術(shù)只是大千世界里知識(shí)的一種,個(gè)人博客: https://sunyuhui.com ...
摘要:當(dāng)面試中讓我解釋一下閉包時(shí)我懵逼了。這個(gè)解釋開(kāi)始可能有點(diǎn)晦澀,讓我們抽絲剝繭摘下閉包的真面目。此文不詳述作用域有專門的主題闡述,不過(guò)作用域是理解閉包原理的基礎(chǔ)。這才是閉包的真正便利之處。閉包使用不當(dāng)就會(huì)很坑。 原文鏈接 為什么深度學(xué)習(xí)JavaScript? JavaScript如今是最流行的編程語(yǔ)言之一。它運(yùn)行在瀏覽器、服務(wù)器、移動(dòng)設(shè)備、桌面應(yīng)用,也可能包括冰箱。無(wú)需我舉其他再多不相干...
摘要:在運(yùn)行腳本時(shí),需要顯示的指定對(duì)象。大對(duì)象區(qū)每一個(gè)區(qū)域都是由一組內(nèi)存頁(yè)構(gòu)成的。這里是唯一擁有執(zhí)行權(quán)限的內(nèi)存區(qū)。換句話說(shuō),是該對(duì)象被之后所能回收到內(nèi)存的總和。一旦活躍對(duì)象已被移出,則在舊的半空間中剩下的任何死亡對(duì)象被丟棄。 內(nèi)存管理 本文以V8為背景 對(duì)之前的文章進(jìn)行重新編輯,內(nèi)容做了很多的調(diào)整,使其具有邏輯更加緊湊,內(nèi)容更加全面。 1. 基礎(chǔ)概念 1.1 生命周期 不管什么程序語(yǔ)言,內(nèi)存...
摘要:內(nèi)部維護(hù)一個(gè)叫的局部變量,數(shù)組類型,用于存儲(chǔ)購(gòu)買的物品清單。分析看到這題的第一反應(yīng)就是用構(gòu)造函數(shù)來(lái)寫。二屬性外部只能訪問(wèn)不能修改這個(gè)用閉包也能解決,但是這樣記不能通過(guò)構(gòu)造函數(shù)來(lái)實(shí)現(xiàn)了,背離了初衷,不行不過(guò)我后面還是會(huì)給出這種寫法。 背景 作為一個(gè)前端新人,免不了加各種群,和其他小伙伴們一起學(xué)習(xí)(chui bi),互相幫助(bi can)。前幾天一個(gè)小伙伴在群里發(fā)了道自己去面試的筆試題,...
閱讀 1168·2021-10-14 09:43
閱讀 1226·2021-10-11 11:07
閱讀 3167·2021-08-18 10:23
閱讀 1543·2019-08-29 16:18
閱讀 1061·2019-08-28 18:21
閱讀 1544·2019-08-26 12:12
閱讀 3829·2019-08-26 10:11
閱讀 2567·2019-08-23 18:04