亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

詳解JavaScript中的作用域鏈與閉包

 更新時間:2022年11月30日 10:18:51   作者:大眼睛圖圖  
這篇文章主要為大家詳細介紹一下JavaScript中的作用域鏈與閉包的使用,文中的示例代碼講解詳細,對我們學(xué)習(xí)JavaScript有一定的幫助,需要的可以參考一下

作用域鏈

首先來看看這段代碼:

var a = '喜羊羊';
function A(){
    console.log(a);
    a = '美羊羊';
    function B(){
        console.log(a);
    }
    B();
}
A();

在這里毫無疑問結(jié)果肯定是我們想到的先打印喜羊羊,再打印美羊羊。因為作用域鏈嘛,如果當(dāng)前層沒找到,那么就去當(dāng)前層的上一級找。

那么再看這道

function bar() {
    console.log(myName)
}
function foo() {
    var myName = "極客邦"
    bar()
}
var myName = "極客時間"
foo()

是不是感覺是打印極客邦?如果是的話,那么恭喜你,掉坑里了。(還不趕快爬起來,補一補作用域鏈的知識)。

為什么打印不是極客邦而是極客時間呢?

既然問題出現(xiàn)在了對作用域鏈的理解上,那么就再回到作用域鏈的定義上吧。

其實在每個執(zhí)行上下文的變量環(huán)境中,都包含了一個外部引用,用來指向外部的執(zhí)行上下文,我們把這個外部引用稱為 outer。

比如上面那段代碼在查找 myName 變量時,如果在當(dāng)前的變量環(huán)境中沒有查找到,那么 JavaScript 引擎會繼續(xù)在 outer 所指向的執(zhí)行上下文中查找

為了直觀理解,你可以看下面這張圖:

看到這張圖我猜你又納悶了,為什么bar函數(shù)創(chuàng)建的執(zhí)行上下文中的outer會指向全局??

哈哈哈,這里就要涉及到了詞法作用域了

詞法作用域

詞法作用域就是指作用域是由代碼中函數(shù)聲明的位置來決定的,所以詞法作用域是靜態(tài)的作用域,通過它就能夠預(yù)測代碼在執(zhí)行過程中如何查找標識符。

這么講可能不太好理解,你可以看下面這張圖:

從圖中可以看出,詞法作用域就是根據(jù)代碼的位置來決定的,其中 main 函數(shù)包含了 bar 函數(shù),bar 函數(shù)中包含了 foo 函數(shù),因為 JavaScript 作用域鏈是由詞法作用域決定的,所以整個詞法作用域鏈的順序是:foo 函數(shù)作用域—>bar 函數(shù)作用域—>main 函數(shù)作用域—> 全局作用域。

明白了詞法作用域,那么我們再回到剛剛的問題。

為什么bar函數(shù)創(chuàng)建的執(zhí)行上下文中的outer會指向全局

這是因為根據(jù)詞法作用域,而詞法作用域又是根據(jù)代碼的位置,而bar函數(shù)代碼的位置就是包裹在全局下,而喜羊羊那個例子中的B函數(shù)是在A函數(shù)的環(huán)境下,所以會造成它們的詞法作用域鏈不同,也就導(dǎo)致函數(shù)作用域鏈不同了。

所以我們才有那句話詞法作用域是代碼編譯階段就決定好的,和函數(shù)是怎么調(diào)用的沒有關(guān)系。

也就是只和代碼位置有關(guān),和函數(shù)直接如何調(diào)用沒關(guān)系

閉包

老生常談的問題,這次再從一個更深入的角度來理解一下。

看下面這段代碼:

function foo() {
    var myName = "極客時間"
    let test1 = 1
    const test2 = 2
    var innerBar = {
        getName:function(){
            console.log(test1)
            return myName
        },
        setName:function(newName){
            myName = newName
        }
    }
    return innerBar
}
var bar = foo()
bar.setName("極客邦")
bar.getName()
console.log(bar.getName())

這段代碼乍一看沒有什么問題,但是這里有一個細節(jié)很多人會忽視。

在foo()執(zhí)行完將返回值給bar時,這里foo函數(shù)會從調(diào)用棧中彈出,變量都會被回收。既然變量都被回收了,那么bar.setName()這些調(diào)用方法從何而來??

foo執(zhí)行完后的情況可以參考下圖:

從上圖可以看出,foo 函數(shù)執(zhí)行完成之后,其執(zhí)行上下文從棧頂彈出了,但是由于返回的 setNamegetName 方法中使用了 foo 函數(shù)內(nèi)部的變量 myNametest1,所以這兩個變量依然保存在內(nèi)存中。這像極了 setNamegetName 方法背的一個專屬背包,無論在哪里調(diào)用了 setName getName 方法,它們都會背著這個foo函數(shù)的專屬背包。

之所以是專屬背包,是因為除了 setNamegetName 函數(shù)之外,其他任何地方都是無法訪問該背包的,我們就可以把這個背包稱為 foo 函數(shù)的閉包。

好了,現(xiàn)在我們終于可以給閉包一個正式的定義了。在 JavaScript 中,根據(jù)詞法作用域的規(guī)則,內(nèi)部函數(shù)總是可以訪問其外部函數(shù)中聲明的變量,當(dāng)通過調(diào)用一個外部函數(shù)返回一個內(nèi)部函數(shù)后,即使該外部函數(shù)已經(jīng)執(zhí)行結(jié)束了,但是內(nèi)部函數(shù)引用外部函數(shù)的變量依然保存在內(nèi)存中,我們就把這些變量的集合稱為閉包 比如外部函數(shù)是 foo,那么這些變量的集合就稱為 foo 函數(shù)的閉包。

用一句話概括就是

能夠訪問其他函數(shù)內(nèi)部變量的函數(shù),被稱為 閉包。

(我們理解可以這么理解,但是和面試官說的當(dāng)然可以把這個例子說一下,這直接上升到了一個理解什么是閉包的新高度了)

到此這篇關(guān)于詳解JavaScript中的作用域鏈與閉包的文章就介紹到這了,更多相關(guān)JavaScript作用域鏈 閉包內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • js實現(xiàn)百度淘寶搜索功能

    js實現(xiàn)百度淘寶搜索功能

    這篇文章主要為大家詳細介紹了js實現(xiàn)百度淘寶搜索功能,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2020-02-02
  • JavaScript ES5標準中新增的Array方法

    JavaScript ES5標準中新增的Array方法

    這篇文章主要介紹了JavaScript ES5標準中新增的Array方法 的相關(guān)資料,需要的朋友可以參考下
    2016-06-06
  • JavaScript創(chuàng)建對象的方式小結(jié)(4種方式)

    JavaScript創(chuàng)建對象的方式小結(jié)(4種方式)

    這篇文章主要介紹了JavaScript創(chuàng)建對象的方式,結(jié)合實例形式總結(jié)分析了四種創(chuàng)建對象的方式,并附帶分析了JavaScript對象復(fù)制的技巧,需要的朋友可以參考下
    2015-12-12
  • 基于JavaScript實現(xiàn)控制下拉列表

    基于JavaScript實現(xiàn)控制下拉列表

    這篇文章主要介紹了基于JavaScript實現(xiàn)控制下拉列表,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2020-05-05
  • 詳解js正則表達式驗證時間格式xxxx-xx-xx形式

    詳解js正則表達式驗證時間格式xxxx-xx-xx形式

    本篇文章主要介紹了詳解js正則表達式驗證時間格式xxxx-xx-xx形式,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-02-02
  • 原生javascript實現(xiàn)DIV拖拽并計算重復(fù)面積

    原生javascript實現(xiàn)DIV拖拽并計算重復(fù)面積

    這篇文章主要介紹了使用原生javascript實現(xiàn)DIV拖拽并計算重復(fù)面積的方法及示例代碼分享,效果十分漂亮,需要的朋友可以參考下
    2015-01-01
  • javascript一點特殊用法

    javascript一點特殊用法

    javascript中函數(shù)的特殊性與普通,對待函數(shù)可以像對待普通變量一樣
    2008-05-05
  • JS中==、===你分清楚了嗎

    JS中==、===你分清楚了嗎

    這篇文章主要介紹了JS中==、===你分清楚了嗎,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-03-03
  • 編寫更好的JavaScript條件式和匹配條件的技巧(小結(jié))

    編寫更好的JavaScript條件式和匹配條件的技巧(小結(jié))

    這篇文章主要介紹了編寫更好的JavaScript條件式和匹配條件的技巧(小結(jié)),文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-06-06

最新評論