摘要:閉包帶來的問題內(nèi)存占用由于閉包使用其它函數(shù)內(nèi)的變量,所以垃圾回收機(jī)制不會對閉包相關(guān)的函數(shù)進(jìn)行回收,占用內(nèi)存空間。
什么是閉包?
“在函數(shù)內(nèi)使用其它函數(shù)內(nèi)的變量,是為閉包”
【例1】 function a() { let num = 100; return function b() { console.log(num) } } var c = a() c() // 100
在例 1 中,a 為外層函數(shù),a中返回了一個內(nèi)部函數(shù) b , 函數(shù) b 中使用了 a 中的 num 變量。此時,函數(shù) b 就形成了一個閉包。
閉包的用處是什么?在JavaScript中,作用域鏈?zhǔn)沟米幼饔糜蚰軌蜃x取到父作用域的變量【見例2】,而反過來,父作用域無法直接獲取子作用域的變量【見例3】。
【例2】 let num = 100 function a() { console.log(num) } a() // 100 【例3】 function a() { let num = 100 } console.log(num) // error: not defined
當(dāng)我們想在父作用域使用子作用域的值時該怎么辦呢?
答:那就在函數(shù)內(nèi)部再定一個函數(shù),將其作為返回值即可【例4】。
【例4】 function a() { let num = 100 return function b() { return num } } var x = a() console.log(x()) // 100
例 4 中,函數(shù) b 作為函數(shù) a 的內(nèi)部函數(shù),可以訪問 a 中的變量 num,于是我們將函數(shù) b 作為返回值,我們通過操作 b 來訪問 a 的變量。
上述利用閉包的特性來實(shí)現(xiàn)外部對內(nèi)部的訪問,便是閉包最基本的應(yīng)用。
閉包的應(yīng)用場景一般來說,我們只想讓外界使用我們暴露出去的方法,而方法涉及到的變量計(jì)算想要封裝在函數(shù)內(nèi)部,以避免被有意/無意地修改變量值,此時,便可利用閉包來進(jìn)行變量封裝以控制權(quán)限【例5】。
【例5】 // 判斷輸入的變量是否是第一次輸入 function isFirstVisit() { let _list = [] return function (id) { if (_list.indexOf(id) >= 0) { console.log("Exist!") } else { _list.push(id) console.log("Added~") } } } let firstVisit = isFirstVisit() firstVisit(5) // Added~ firstVisit(5) // Exist! firstVisit(10) // Added~
將 isFirstVisit 的返回值賦給 firstVisit ,然后通過使用 firstVisit 進(jìn)行判斷,因?yàn)楸┞督o外界使用的是 firstVisit 函數(shù),所以只能使用該函數(shù)定義的方法,而無法對 _list 進(jìn)行任何修改,保證了數(shù)據(jù)的私密性。
函數(shù)柯里化就是把一個函數(shù)接收多個參數(shù)進(jìn)行處理,轉(zhuǎn)變?yōu)榻邮諉我粎?shù),然后返回一個新函數(shù)接收下一個參數(shù)【見例6】。
【例6】 // 普通函數(shù) function sum(x, y) { return x + y } // 函數(shù)柯里化 function curryingSum(x) { return function(y) { return x + y } }
這里函數(shù)柯里化后的內(nèi)部函數(shù)所使用的 x,就是其父作用域的變量,此時的內(nèi)部函數(shù)就是一個閉包。
函數(shù)柯里化應(yīng)用之 參數(shù)復(fù)用
【例7】 function check(reg, txt) { return reg.test(txt) } // 檢驗(yàn)是否含有數(shù)字 check(/d+/g, "test") // false check(/d+/g, "abc") // false check(/d+/g, "2dd") // true // 柯里化后 function curryingCheck(reg) { return function(txt) { return reg.test(txt) } } let hasNumber = curryingCheck(/d+/g) hasNumber("test") // false hasNumber("abc") // false hasNumber("2dd") // true
通過上例可以看到,直接使用check函數(shù),第一個參數(shù)“正則判斷語句”在每次使用時都需要輸入,既不美觀也不方便。對其進(jìn)行函數(shù)柯里化后,只需輸入一次正則判斷語句,便可對判斷函數(shù)進(jìn)行復(fù)用。
閉包帶來的問題由于閉包使用其它函數(shù)內(nèi)的變量,所以垃圾回收機(jī)制不會對閉包相關(guān)的函數(shù)進(jìn)行回收,占用內(nèi)存空間。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/104309.html
摘要:所以,有另一種說法認(rèn)為閉包是由函數(shù)和與其相關(guān)的引用環(huán)境組合而成的實(shí)體。所以本文中將以維基百科中的定義為準(zhǔn)即在計(jì)算機(jī)科學(xué)中,閉包,又稱詞法閉包或函數(shù)閉包,是引用了自由變量的函數(shù)。 閉包(closure)是JavaScript中一個神秘的概念,許多人都對它難以理解,我也一直處于似懂非懂的狀態(tài),前幾天深入了解了一下執(zhí)行環(huán)境以及作用域鏈,可戳查看詳情,而閉包與作用域及作用域鏈的關(guān)系密不可分,所...
摘要:執(zhí)行環(huán)境變量對象活動對象作用域鏈執(zhí)行環(huán)境,為簡單起見,有時也稱為環(huán)境是中最為重要的一個概念。作用域鏈的用途,是保證對執(zhí)行環(huán)境有權(quán)訪問的所有變量和函數(shù)的有序訪問。閉包垃圾回收機(jī)制先介紹下垃圾回收機(jī)制。 執(zhí)行環(huán)境、變量對象 / 活動對象、作用域鏈 執(zhí)行環(huán)境(executioncontext,為簡單起見,有時也稱為環(huán)境)是JavaScript中最為重要的一個概念。執(zhí)行環(huán)境定義了變量或函數(shù)有...
摘要:但閉包的情況不同嵌套函數(shù)的閉包執(zhí)行后,,然后還在被回收閉包會使變量始終保存在內(nèi)存中,如果不當(dāng)使用會增大內(nèi)存消耗。每個函數(shù),不論多深,都可以認(rèn)為是全局的子作用域,可以理解為閉包。 閉包(closure)是Javascript語言的一個難點(diǎn),也是它的特色,很多高級應(yīng)用都要依靠閉包實(shí)現(xiàn)。 閉包的特性 閉包有三個特性: 1.函數(shù)嵌套函數(shù) 2.函數(shù)內(nèi)部可以引用外部的參數(shù)和變量 3.參數(shù)和變量不會...
摘要:使用單引號雙引號和三引號或來表示字符串。不可變的集合函數(shù)會以字典類型返回當(dāng)前位置的全部全局變量。用于將進(jìn)制整數(shù)轉(zhuǎn)換成進(jìn)制,以字符串形式表示。返回字符串中最大的字母,或數(shù)組中的最大值。的作用就是減少了單行函數(shù)的定義。 問題答案由本人整理 1.基礎(chǔ)語法是否熟悉?介紹一下 Python和其他語言最大的區(qū)別就是使用行和縮進(jìn),而不是大括號({})或者分號(;)來控制類、函數(shù)或者邏輯判斷。Pyt...
閱讀 657·2021-11-22 15:32
閱讀 2745·2021-11-19 09:40
閱讀 2337·2021-11-17 09:33
閱讀 1300·2021-11-15 11:36
閱讀 1895·2021-10-11 10:59
閱讀 1503·2019-08-29 16:41
閱讀 1809·2019-08-29 13:45
閱讀 2181·2019-08-26 13:36