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