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