摘要:本質與解析當函數(shù)可以記住并訪問所在的詞法作用域時,就產(chǎn)生了閉包,即使函數(shù)是在當前詞法作用域之外執(zhí)行。
本質與解析
當函數(shù)可以記住并訪問所在的詞法作用域時,就產(chǎn)生了閉包,即使函數(shù)是在當前詞法作用域之外執(zhí)行。
function outter() { var a = 1 function inner() { console.log(a) } return inner } var accept = outter() accept() // 1
在此例中,將內部函數(shù)inner作為返回值,當outter函數(shù)執(zhí)行后,賦值給accept,并且調用accept;實際上調用了inner函數(shù),它在自己定義的詞法作用域以外的地方執(zhí)行。
通常在outter函數(shù)執(zhí)行完成之后,由于js的垃圾回收機制,其內部的作用域會被銷毀回收,但是由于閉包的存在,accept持有對inner的引用,而inner聲明的位置為outter的內部作用域,因此該作用能夠一直存活
面試常見的閉包考題就是循環(huán)閉包。例如:
for (var i=0; i<=8; i++) { setTimeout(function () { console.log(i) },1000) }
正常情況下期待每隔一秒輸出1~8,但是實際每秒輸出一個9,其實不難理解,從執(zhí)行棧來看,延遲函數(shù)會在整個for循環(huán)執(zhí)行完成之后才會執(zhí)行,即使setTimeout設置的延遲時間是0,同時其被封閉在全局的作用域中的,因此每次得到的都是對全局i變量的引用,實際上只有一個i。
可以通過立即執(zhí)行函數(shù)將作用域封閉起來,同時通過自己定義一個變量j在每次迭代中存儲i的值來解決這個問題,代碼如下:
for (var i=0; i<=8; i++) { (function () { var j = i setTimeout(function () { console.log(j) },1000) })(i) }
還有更加簡單的解決方案,可以通過let聲明來劫持塊作用域,并且在這個塊作用域中聲明一個變量,代碼如下:
for (let i=0; i<=8; i++) { setTimeout(function () { console.log(i) },1000) }
for循環(huán)頭部的let聲明會有一個特殊行為,這個行為指出變量在循環(huán)的過程中不止被聲明一次,每次迭代都會聲明,隨后每次迭代都會使用上一個迭代結束時的值來初始化這個變量,這就意味著每次循環(huán)都會聲明一個新的i,且會將上一個迭代結束時的值賦給i
模塊模式與閉包模塊模式實例:
function module() { //封閉函數(shù) var arr = [1,2,3] function one() { console.log(arr.join("")) } function another() { arr.push(4) console.log(arr.join("")) } return { one: one, //內部函數(shù) another: another } } var accept = module() accept.one() //123 創(chuàng)建一個新的模塊實例 accept.another() //1234 創(chuàng)建一個新的模塊實例
解析:module是一個函數(shù),需要通過調用它來創(chuàng)建一個模塊實例。其返回一個{key:value}形式的對象,這個對象中包含內部函數(shù)的引用,將其暴露提供調用,且module內部數(shù)據(jù)變量是私有隱藏狀態(tài),這個對象返回值本質上是這個模塊的公共API
分析得出模塊模式需要兩個必備條件:
必須有外部的封閉函數(shù),該函數(shù)必須至少被調用一次(每次調用都會創(chuàng)建一個新的模塊實例)
封閉函數(shù)必須返回至少一個內部函數(shù),這樣內部函數(shù)才能在私有作用域中形成閉包,并且可以訪問或者修改私有的狀態(tài)
模塊機制var MyModules = (function Manager() { var modules = {}; function define(name, deps, impl) { for (var i=0; i"one"和"another"兩個模塊都是通過公共API函數(shù)來定義,并且"another"接受"one"的實例作為參數(shù)注入,這就是模塊之間可以存在依賴關系
以上內容是個人的一點總結,如果有錯誤或不嚴謹?shù)牡胤?,歡迎批評指正,如果喜歡,歡迎點贊收藏
文章版權歸作者所有,未經(jīng)允許請勿轉載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/88624.html
摘要:大名鼎鼎的閉包面試必問。閉包的作用是什么??吹介]包在哪了嗎閉包到底是什么五年前,我也被這個問題困擾,于是去搜了并總結下來。關于閉包的謠言閉包會造成內存泄露錯。閉包里面的變量明明就是我們需要的變量,憑什么說是內存泄露這個謠言是如何來的因為。 本文為饑人谷講師方方原創(chuàng)文章,首發(fā)于 前端學習指南。 大名鼎鼎的閉包!面試必問。請用自己的話簡述 什么是「閉包」。 「閉包」的作用是什么。 首先...
摘要:完美的閉包,對,閉包就這么簡單。這僅僅是閉包的一部分,閉包利用函數(shù)作用域達到了訪問外層變量的目的。此時一個完整的閉包實現(xiàn)了,的垃圾回收機制由于閉包的存在無法銷毀變量。 1.閉包是指有權訪問另一個函數(shù)作用域中的變量的函數(shù)。 上面這段話來自 javascript 高級程序設計 第三版 P178 。作者說閉包是一個函數(shù),它有訪問另一個函數(shù)作用域中的變量的能力。 2.函數(shù)訪問它被創(chuàng)建時所處的...
摘要:到底什么是閉包這個問題在面試是時候經(jīng)常都會被問,很多小白一聽就懵逼了,不知道如何回答好。上面這么說閉包是一種特殊的對象。閉包的注意事項通常,函數(shù)的作用域及其所有變量都會在函數(shù)執(zhí)行結束后被銷毀。從而使用閉包模塊化代碼,減少全局變量的污染。 閉包,有人說它是一種設計理念,有人說所有的函數(shù)都是閉包。到底什么是閉包?這個問題在面試是時候經(jīng)常都會被問,很多小白一聽就懵逼了,不知道如何回答好。這個...
閱讀 1297·2021-11-04 16:09
閱讀 3484·2021-10-19 11:45
閱讀 2396·2021-10-11 10:59
閱讀 1010·2021-09-23 11:21
閱讀 2762·2021-09-22 10:54
閱讀 1129·2019-08-30 15:53
閱讀 2600·2019-08-30 15:53
閱讀 3477·2019-08-30 12:57