成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

【前端工程師手冊(cè)】JavaScript之閉包

CarlBenjamin / 3367人閱讀

摘要:閉包確實(shí)是一個(gè)說爛了的概念,校招社招都會(huì)被問到,今天總結(jié)一番。先下定義,閉包是函數(shù)和該函數(shù)的詞法作用域的組合。在這個(gè)栗子里,函數(shù)以及它對(duì)變量的引用就構(gòu)成了閉包。閉包和作用域?qū)τ陂]包和作用域的關(guān)系,我的理解是閉包其實(shí)就是作用域的延伸。

閉包確實(shí)是一個(gè)說爛了的概念,校招社招都會(huì)被問到,今天總結(jié)一番。
先下定義,閉包是函數(shù)和該函數(shù)的詞法作用域的組合。其實(shí)這個(gè)定義是比較教條的,可以直白的理解為閉包是一個(gè)函數(shù),且這個(gè)函數(shù)使用了既沒在它內(nèi)部聲明且不是它的參數(shù)的變量。
舉個(gè)栗子,

function foo() { 
    var a = 2;
    function bar() { 
        console.log( a );
    }
    return bar; 
}
var baz = foo();
baz(); // 2

按照常理,foo函數(shù)在執(zhí)行完畢之后會(huì)銷毀掉其內(nèi)部的變量a,但是bar函數(shù)內(nèi)部保持著對(duì)a的引用,所以通過調(diào)用foo()把bar的引用賦給了baz,運(yùn)行baz()依然可以打印出a。在這個(gè)栗子里,函數(shù)bar以及它對(duì)變量a的引用就構(gòu)成了閉包。

閉包和作用域

對(duì)于閉包和作用域的關(guān)系,我的理解是閉包其實(shí)就是作用域的延伸。
由于在JavaScript中函數(shù)內(nèi)部可以使用函數(shù)外部的變量,所有有時(shí)候會(huì)不知不覺的產(chǎn)生閉包,假如在上面那個(gè)代碼片段中,不允許函數(shù)內(nèi)部使用函數(shù)外部的變量,閉包也就無從談起了。

閉包有什么用?

模擬私有變量和私有方法

var Dog = (function(){
    var privateVal = "dog"
    function doing(val) {
        console.log(privateVal + " " + val)
    }

    return {
        run: function(){
            doing("run")
        },
        bark: function(){
            doing("bark")
        }
    }
})()

Dog.run()    // dog run
Dog.bark()   //  dog bark

可以看到的是,run和bark這兩個(gè)閉包分享了同一個(gè)詞法作用域,且都引用了私有方法doing。這樣,我們就可以只向外暴露run和bark兩個(gè)公共接口而隱藏私有的變量和方法。

閉包與循環(huán)

或許這是面試中出現(xiàn)最多的問題...

for(var i = 1;i <= 5;i++) {
    setTimeout(function() {
        console.log(i)
    }, i*1000)
}
// 每隔一秒打印一個(gè)6,共打印5次

為什么事與愿違,而不是按照我們所想的依次的間隔1秒打印出1,2,3,4,5呢?首先,這段循環(huán)產(chǎn)生了5個(gè)閉包,而且最重要的是這5個(gè)閉包都處在同一個(gè)作用域中,也就是說它們引用的是同一個(gè)i,當(dāng)for循環(huán)結(jié)束時(shí),i變成了6。所以,5個(gè)匿名函數(shù)執(zhí)行時(shí)會(huì)依次的去打印那同一個(gè)i,所以就打印出了5個(gè)6。
如何解決?
之前也說了讓這5個(gè)閉包處于不同的作用域且讓它們?cè)诟髯缘淖饔糜蛑袚碛兴鼈兏髯缘膇即可。
可以使用自執(zhí)行函數(shù)來創(chuàng)建一個(gè)新的作用域

for(var i = 1;i <= 5;i++) {
    (function(k){
        setTimeout(function() {
        console.log(k)
    }, k*1000)
    })(i)
}

在這個(gè)代碼片段中,每一個(gè)setTimeout都處于一個(gè)獨(dú)立的作用域中,且都引用了它們各自的k,并不是指向了外層作用域的i,所以就會(huì)打印出1,2,3,4,5
也可以使用let

for(let i = 1;i <= 5;i++) {
    setTimeout(function() {
        console.log(i)
    }, i*1000)
}

for 循環(huán)頭部的 let 不僅將 i 綁定到了 for 循環(huán)的塊中,事實(shí)上它將其重新綁定到了循環(huán)的每一個(gè)迭代中,確保使用上一個(gè)循環(huán)迭代結(jié)束時(shí)的值重新進(jìn)行賦值。
其實(shí)使用let的本質(zhì)是

for(let i = 1;i <= 5;i++) {
    let i = 上次迭代結(jié)束的i
    setTimeout(function() {
        console.log(i)
    }, i*1000)
}

其實(shí)閉包就這么多東西,而且主要是作用域的概念,作用域明白了,閉包也就明白了。
that"s all, thank you.

參考資料
深入理解JavaScript系列-閉包
MDN-閉包
《你不知道的JavaScript-上卷》
「每日一題」JS 中的閉包是什么?

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/94942.html

相關(guān)文章

  • JavaScript系列(四) - 收藏集 - 掘金

    摘要:函數(shù)式編程前端掘金引言面向?qū)ο缶幊桃恢币詠矶际侵械闹鲗?dǎo)范式。函數(shù)式編程是一種強(qiáng)調(diào)減少對(duì)程序外部狀態(tài)產(chǎn)生改變的方式。 JavaScript 函數(shù)式編程 - 前端 - 掘金引言 面向?qū)ο缶幊桃恢币詠矶际荍avaScript中的主導(dǎo)范式。JavaScript作為一門多范式編程語言,然而,近幾年,函數(shù)式編程越來越多得受到開發(fā)者的青睞。函數(shù)式編程是一種強(qiáng)調(diào)減少對(duì)程序外部狀態(tài)產(chǎn)生改變的方式。因此,...

    cfanr 評(píng)論0 收藏0
  • 前端知識(shí)點(diǎn)整理

    摘要:難怪超過三分之一的開發(fā)人員工作需要一些知識(shí)。但是隨著行業(yè)的飽和,初中級(jí)前端就業(yè)形勢(shì)不容樂觀。整個(gè)系列的文章大概有篇左右,從我是如何成為一個(gè)前端工程師,到各種前端框架的知識(shí)。 為什么 call 比 apply 快? 這是一個(gè)非常有意思的問題。 作者會(huì)在參數(shù)為3個(gè)(包含3)以內(nèi)時(shí),優(yōu)先使用 call 方法進(jìn)行事件的處理。而當(dāng)參數(shù)過多(多余3個(gè))時(shí),才考慮使用 apply 方法。 這個(gè)的原因...

    Lowky 評(píng)論0 收藏0
  • 前端知識(shí)點(diǎn)整理

    摘要:難怪超過三分之一的開發(fā)人員工作需要一些知識(shí)。但是隨著行業(yè)的飽和,初中級(jí)前端就業(yè)形勢(shì)不容樂觀。整個(gè)系列的文章大概有篇左右,從我是如何成為一個(gè)前端工程師,到各種前端框架的知識(shí)。 為什么 call 比 apply 快? 這是一個(gè)非常有意思的問題。 作者會(huì)在參數(shù)為3個(gè)(包含3)以內(nèi)時(shí),優(yōu)先使用 call 方法進(jìn)行事件的處理。而當(dāng)參數(shù)過多(多余3個(gè))時(shí),才考慮使用 apply 方法。 這個(gè)的原因...

    snowLu 評(píng)論0 收藏0
  • JavaScript - 收藏集 - 掘金

    摘要:插件開發(fā)前端掘金作者原文地址譯者插件是為應(yīng)用添加全局功能的一種強(qiáng)大而且簡(jiǎn)單的方式。提供了與使用掌控異步前端掘金教你使用在行代碼內(nèi)優(yōu)雅的實(shí)現(xiàn)文件分片斷點(diǎn)續(xù)傳。 Vue.js 插件開發(fā) - 前端 - 掘金作者:Joshua Bemenderfer原文地址: creating-custom-plugins譯者:jeneser Vue.js插件是為應(yīng)用添加全局功能的一種強(qiáng)大而且簡(jiǎn)單的方式。插....

    izhuhaodev 評(píng)論0 收藏0
  • 雙十二大前端程師讀書清單

    摘要:本文最早為雙十一而作,原標(biāo)題雙大前端工程師讀書清單,以付費(fèi)的形式發(fā)布在上。發(fā)布完本次預(yù)告后,捕捉到了一個(gè)友善的吐槽讀書清單也要收費(fèi)。這本書便從的異步編程講起,幫助我們?cè)O(shè)計(jì)快速響應(yīng)的網(wǎng)絡(luò)應(yīng)用,而非簡(jiǎn)單的頁(yè)面。 本文最早為雙十一而作,原標(biāo)題雙 11 大前端工程師讀書清單,以付費(fèi)的形式發(fā)布在 GitChat 上。發(fā)布之后在讀者圈群聊中和讀者進(jìn)行了深入的交流,現(xiàn)免費(fèi)分享到這里,不足之處歡迎指教...

    余學(xué)文 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<