亚洲中字慕日产2020,大陆极品少妇内射AAAAAA,无码av大香线蕉伊人久久,久久精品国产亚洲av麻豆网站

資訊專欄INFORMATION COLUMN

Jeffrrey / 1642人閱讀

大白話解釋作用域和閉包是個(gè)啥 作用域的分類

常見(jiàn)的變量作用域就是 靜態(tài)作用域(詞法作用域)動(dòng)態(tài)作用域 。詞法作用域注重的是 write-time ,即 編程時(shí)的上下文 ,而 動(dòng)態(tài)作用域 則注重的是 run-time ,即 運(yùn)行時(shí)上下文 。詞法作用域中我們需要知道一個(gè)函數(shù) 在什么地方被定義 ,而動(dòng)態(tài)作用域中我們需要關(guān)心的是函數(shù) 在什么地方被調(diào)用

而 javascript 使用的則是詞法作用域

let value = 1

function foo() {
    console.log(value)
}

function bar() {
    let value = 2
    foo()
}

bar() // 1

在 javascript 解析模式中,當(dāng) foo 被調(diào)用的時(shí)候:

檢查 foo 函數(shù)內(nèi)是否存在 value

存在則使用這個(gè) value

不存在則根據(jù)書寫代碼的位置查找上一層代碼(這里的 window),找到 value 為 1

在動(dòng)態(tài)作用域的解析模式中,當(dāng) foo 被調(diào)用的時(shí)候:

檢查 foo 函數(shù)內(nèi)是否存在 value

存在則使用這個(gè) value

不存在則根據(jù)調(diào)用該函數(shù)的作用域中去尋找也就是這里的 bar 函數(shù),找到 value 為 2

在從內(nèi)層到外層的變量搜索過(guò)程中,當(dāng)前作用域到外層作用域再到更外層作用域直到最外層的全局作用域,整個(gè)搜尋軌跡就是 作用域鏈

變量的兩種查找類型

一種是 rhs 一種是 lhs

假設(shè)有這么一段代碼:

console.log(a) // 輸出 undefined
console.log(a2) // 報(bào)錯(cuò) a2 is not defined
var a = 1

上述代碼實(shí)際上在變量提升的作用下應(yīng)該是下面這個(gè)順序:

var a
console.log(a) // 輸出 undefined
console.log(a2) // 報(bào)錯(cuò) a2 is not defined
a = 1

第一個(gè) console 輸出 undefined 因?yàn)檫€未執(zhí)行賦值操作,查詢過(guò)程是 rhs 也就是 right-hand-side

第二個(gè) console 報(bào)錯(cuò),是因?yàn)?rhs 查詢 a2 變量不存在因此報(bào)錯(cuò)

a = 1 則是賦值操作,也就是 lhs,英文 left-hand-side

閉包

閉包是啥?閉包就是從函數(shù)外部訪問(wèn)函數(shù)內(nèi)部的變量,函數(shù)內(nèi)部的變量可以持續(xù)存在的一種實(shí)現(xiàn)。

在了解了詞法作用域和變量的查詢方式之后,我們看看一個(gè)簡(jiǎn)單的閉包的實(shí)現(xiàn)邏輯:

function f() {
    let num = 1 // 里面的變量
    function add() {
        num += 1
    }
    function log() {
        console.log(num)
    }
    return { add, log } // 我要到外面去了
}

const { add, log } = f()

log() // 1 我從里面來(lái),我在外面被調(diào)用,還是可以獲得里面的變量
add()
log() // 2

首先定義一個(gè) f 函數(shù),函數(shù)內(nèi)部維護(hù)一個(gè)變量 num,然后定義兩個(gè)函數(shù) add 和 log

add 函數(shù)每次調(diào)用會(huì)增加 num 的值

log 函數(shù)每次調(diào)用會(huì)打印 num 的值

然后我們將兩個(gè)函數(shù)通過(guò) return 方法返回

緊接著先調(diào)用外部的 log 方法打印 f 方法維護(hù)的 num,此時(shí)為 1

然后調(diào)用外部的 add 方法增加 num 的值

最后再次調(diào)用 log 方法打印 num,此時(shí)則為 2

為什么外部定義的 add 函數(shù)可以訪問(wèn) f 函數(shù)內(nèi)部的變量呢。正常情況下外部作用域不可訪問(wèn)內(nèi)部作用域的變量,但我們將內(nèi)部訪問(wèn)其內(nèi)部變量的方法“導(dǎo)出”出去,以至于可以從外部直接調(diào)用函數(shù)內(nèi)部的方法,這樣我們就可以從函數(shù)的外部訪問(wèn)函數(shù)內(nèi)部的變量了。

經(jīng)典的 for 循環(huán)問(wèn)題
arr = []
for (var i = 0; i < 10; i ++) {
    arr[i] = function() {
        console.log(i)
    }
}
arr[2]() // 10

首先我們知道 for 循環(huán)體內(nèi)的 i 實(shí)際上會(huì)被定義在全局作用域中

每次循環(huán)我們都將 function 推送到一個(gè) arr 中,for 循環(huán)執(zhí)行完畢后,arr 中張這樣:

隨后我們執(zhí)行代碼 arr[2]() 此時(shí) arr[2] 對(duì)應(yīng)的函數(shù) function(){ console.log(i) } 會(huì)被觸發(fā)

函數(shù)嘗試搜索函數(shù)局部作用域中的 i 變量,搜索不到則會(huì)繼續(xù)向外層搜索,i 被定義到了外層,因此會(huì)直接采用外層的 i,就是這里的全局作用域中的 i,等到這個(gè)時(shí)候調(diào)用這個(gè)函數(shù),i 早已變成 10 了

那么有什么方法能夠避免出現(xiàn)這種情況嗎?

ES6 之前的解決方案:

了解了閉包我們就知道了閉包內(nèi)的變量可以持續(xù)存在,所以修改代碼將 arr 中的每一項(xiàng)改為指向一個(gè)閉包:

arr = []
for (var i = 0; i < 10; i ++) {
    arr[i] = (function() { // 這是一個(gè)閉包
        var temp = i // 閉包內(nèi)部維護(hù)一個(gè)變量,這個(gè)變量可以持續(xù)存在
        return function() {
            console.log(temp)
        }
    })()
}

這樣程序就能按照我們的想法運(yùn)行了

ES6 之后的解決方案:

ES6 之后我們就有了塊級(jí)作用域因此代碼可以改為這樣:

arr = []
for (let i = 0; i < 10; i ++) { // 使用 let
    arr[i] = function() {
        console.log(i)
    }
}

在使用 let 之后,我們每次定義 i 都是通過(guò) let i 的方法定義的,這個(gè)時(shí)候 i 不再是被定義到全局作用域中了,而是被綁定在了 for 循環(huán)的塊級(jí)作用域中

因?yàn)槭菈K級(jí)作用域所以對(duì)應(yīng) i 的 arr 每一項(xiàng)都變成了一個(gè)閉包,arr 每一項(xiàng)都在不同的塊級(jí)作用域中因此不會(huì)相互影響

參考:

https://github.com/mqyqingfen...

https://www.datchley.name/bas...

https://segmentfault.com/a/11...

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

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

相關(guān)文章

  • vue中如何實(shí)現(xiàn)的自定義按鈕

    摘要:在實(shí)際開(kāi)發(fā)項(xiàng)目中,有時(shí)我們會(huì)用到自定義按鈕因?yàn)橐粋€(gè)項(xiàng)目中,眾多的頁(yè)面,為了統(tǒng)一風(fēng)格,我們會(huì)重復(fù)用到很多相同或相似的按鈕,這時(shí)候,自定義按鈕組件就派上了大用場(chǎng),我們把定義好的按鈕組件導(dǎo)出,在全局引用,就可以在其他組件隨意使用啦,這樣可以大幅度 在實(shí)際開(kāi)發(fā)項(xiàng)目中,有時(shí)我們會(huì)用到自定義按鈕;因?yàn)橐粋€(gè)項(xiàng)目中,眾多的頁(yè)面,為了統(tǒng)一風(fēng)格,我們會(huì)重復(fù)用到很多相同或相似的按鈕,這時(shí)候,自定義按鈕組件就...

    biaoxiaoduan 評(píng)論0 收藏0
  • JavaScript代碼整潔之道

    摘要:代碼整潔之道整潔的代碼不僅僅是讓人看起來(lái)舒服,更重要的是遵循一些規(guī)范能夠讓你的代碼更容易維護(hù),同時(shí)降低幾率。另外這不是強(qiáng)制的代碼規(guī)范,就像原文中說(shuō)的,。里式替換原則父類和子類應(yīng)該可以被交換使用而不會(huì)出錯(cuò)。注釋好的代碼是自解釋的。 JavaScript代碼整潔之道 整潔的代碼不僅僅是讓人看起來(lái)舒服,更重要的是遵循一些規(guī)范能夠讓你的代碼更容易維護(hù),同時(shí)降低bug幾率。 原文clean-c...

    liaorio 評(píng)論0 收藏0
  • 前端經(jīng)典面試題總結(jié)

    摘要:接著我之前寫的一篇有關(guān)前端面試題的總結(jié),分享幾道比較經(jīng)典的題目第一題考點(diǎn)作用域,運(yùn)算符栗子都會(huì)進(jìn)行運(yùn)算,但是最后之后輸出最后一個(gè)也就是那么其實(shí)就是而且是個(gè)匿名函數(shù),也就是屬于,就輸出第二和第三個(gè)都是類似的,而且作用域是都是輸出最后一個(gè)其實(shí)就 接著我之前寫的一篇有關(guān)前端面試題的總結(jié),分享幾道比較經(jīng)典的題目: 第一題: showImg(https://segmentfault.com/im...

    BlackMass 評(píng)論0 收藏0
  • 私有云那家好-六大私有云廠商詳細(xì)對(duì)比!

    對(duì)比內(nèi)容UCloudStackZStackVMwareQingCloud騰訊TStack華為云Stack優(yōu)勢(shì)總結(jié)?基于公有云自主可控?公有云架構(gòu)私有化部署?輕量化/輕運(yùn)維/易用性好?政府行業(yè)可復(fù)制案例輕量化 IaaS 虛擬化平臺(tái)?輕量化、產(chǎn)品成熟度高?業(yè)內(nèi)好評(píng)度高?功能豐富、交付部署快?中小企業(yè)案例多全套虛擬產(chǎn)品及云平臺(tái)產(chǎn)品?完整生態(tài)鏈、技術(shù)成熟?比較全面且健全的渠道?產(chǎn)品成熟度被市場(chǎng)認(rèn)可,市場(chǎng)占...

    ernest.wang 評(píng)論0 收藏0
  • cross-env使用記錄

    摘要:能跨平臺(tái)地設(shè)置及使用環(huán)境變量讓這一切變得簡(jiǎn)單,不同平臺(tái)使用唯一指令,無(wú)需擔(dān)心跨平臺(tái)問(wèn)題安裝方式改寫使用了環(huán)境變量的常見(jiàn)如在腳本多是里這么配置運(yùn)行,這樣便設(shè)置成功,無(wú)需擔(dān)心跨平臺(tái)問(wèn)題關(guān)于跨平臺(tái)兼容,有幾點(diǎn)注意 cross-env能跨平臺(tái)地設(shè)置及使用環(huán)境變量, cross-env讓這一切變得簡(jiǎn)單,不同平臺(tái)使用唯一指令,無(wú)需擔(dān)心跨平臺(tái)問(wèn)題 1、npm安裝方式 npm i --save-de...

    Michael_Ding 評(píng)論0 收藏0
  • webpack打包插件

    摘要:引入的模塊引入的使用將打包打包的拆分將一部分抽離出來(lái)物理地址拼接優(yōu)化打包速度壓縮代碼,這里使用的是,同樣在的里面添加 const path = require(path); //引入node的path模塊const webpack = require(webpack); //引入的webpack,使用lodashconst HtmlWebpackPlugin = require(ht...

    ChanceWong 評(píng)論0 收藏0

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

0條評(píng)論

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