一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務器之家:專注于服務器技術及軟件下載分享
分類導航

node.js|vue.js|jquery|angularjs|React|json|js教程|

服務器之家 - 編程語言 - JavaScript - JavaScript中作用域鏈的概念及用途講解

JavaScript中作用域鏈的概念及用途講解

2021-08-09 16:54Lpyexplore JavaScript

這篇文章主要介紹了JavaScript中作用域鏈的概念及用途講解,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧

從零開始講解JavaScript中作用域鏈的概念及用途

引言

之前我寫過一篇關于JavaScript中的對象的一篇文章,里面也提到了作用域鏈的概念,相信大家對這個概念還是沒有很深的理解,并且這個概念也是面試中經常問到的,因為這個概念實在太重要了,在我們平時寫代碼時,也可能會因為作用域鏈的問題,而出現莫名其妙的bug,導致我們花費大量的時間都查找不出原因。所以我就準備單獨寫一篇關于作用域鏈的文章,來幫大家更好地理解這個概念。

正文

一、執行環境

首先,我們要引入一個概念,叫做執行環境(下面簡稱環境)。在一個執行環境中,有一個與之關聯的變量對象(下面簡稱對象),在該對象中,儲存著這個執行環境中定義的變量和函數。但這個對象只是個形式上的對象,并不能被外界所訪問到。

例如,在瀏覽器中,我們在全局運行下列代碼,那么當前的執行環境就是window,也就是全局,并且與該全局環境關聯的對象中存儲著定義的變量fruit

?
1
2
3
4
5
6
7
8
9
10
11
12
13
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Title</title>
</head>
<body>
  <script>
    let fruit = 'banana'
    alert(fruit)
  </script>
</body>
</html>

那么,在javascript中,函數也會形成一個環境,例如下列的代碼中,函數的內部就是一個局部的環境,與該環境關聯的對象中存儲著變量my_favorite;而此時全局環境window中,也有一個與之關聯的對象,該對象中存儲著變量fruit 和函數 fn1

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Title</title>
</head>
<body>
  <script>
    let fruit = 'banana'
    alert(fruit)
    function fn1() {
      let my_favorite = 'apple'
      return my_favorite
    }
    fn1()
  </script>
</body>
</html>

二、作用域鏈

看了上面兩個例子,我們對執行環境應該有了一定的了解,那么這里就將引入作用域鏈的概念了,當代碼執行在一個環境中時,會針對環境中儲存變量和函數的對象創建一個作用域鏈,作用域鏈的最前端就是當前環境的對象,如果當前環境是個函數,則作用域鏈的下一部分就是全局的window環境的變量對象。

先來看一下代碼部分

?
1
2
3
4
5
6
7
8
9
10
11
<script>
    let fruit = 'banana'
    function fn() {
        let color = 'red'
        //返回 '我最喜歡的水果是banana,我最喜歡的顏色是red'
        console.log('我最喜歡的水果是' + fruit + ',我最喜歡的顏色是' + color)
    }
    fn()
    //報錯, color is undefined
    console.log('我最喜歡的水果是' + fruit + ',我最喜歡的顏色是' + color)
</script>

首先執行了函數 fn ,此時函數內的作用域鏈就是這樣的

JavaScript中作用域鏈的概念及用途講解

我們看到,在函數 fn 中,我們使用了變量 fruit 和 color,所以此時會從作用域鏈的頭部開始,從第一個活動變量(本例中第一個變量對象就是函數fn的活動變量)中,尋找變量 fruit和 color,發現該變量對象中存在變量color,于是就成功引用了變量color,但是因為沒有找到變量 fruit,于是再沿著作用域鏈往下找到下一個變量對象(本例中第二個活動變量就是全局window的變量對象),發現該變量對象中有我們想要的變量 fruit,則引用該變量 fruit ,同時,因為找到了需要引用的變量,就不會繼續沿著作用域鏈繼續向下尋找了。

我們再來看在函數外,也就是全局window中,也執行了console.log('我最喜歡的水果是' + fruit + ',我最喜歡的顏色是' + color),此時在全局環境中的作用域鏈是這樣的

JavaScript中作用域鏈的概念及用途講解

此時也使用了變量 fruit 和 color,所以這時會從作用域鏈的頭部開始,找到第一個變量對象(本例中第一個活動變量就是window全局變量對象),發現該變量對象中有變量 fruit,所以成功引用該變量對象中的 fruit,但因為沒找到變量 color,所以繼續沿著作用域鏈向下尋找下一個活動變量,但此時已經找到了作用域鏈的尾部,并沒有別的變量對象了,所以也就無法找到變量 color了,所以最后返回的就是 undefined。在本例中我們可以看到,當代碼處于全局環境中時,是沒有訪問函數fn執行環境中的變量color的權力的,這里我們可以這種現象看成是變量color的作用域只是在函數fn的執行環境內。

這就是代碼執行時,作用域鏈起到的作用,所以作用域鏈就保證了執行環境中代碼對變量的有序訪問。

三、塊級作用域

在JavaScript中是沒有塊級作用域的,也就是說,由花括號或小括號封閉起來的區域內沒有自己的作用域,例如這兩個例子

?
1
2
3
4
if(true) {
    var fruit = 'banana'
}
console.log(fruit)  //返回 banana

我們可以看到,if 語句中的花括號內,使用 var 定義了一個變量 fruit,按照作用域鏈的規則來說,外部是無法訪問到該變量的,但是我們可以看到,確實返回了這個變量的值 banana 。

再來看下一個例子

?
1
2
3
4
for(var i=0; i<4; i++) {
    alert(i)
}
console.log(i)  //返回4

在使用 for語句時,我們在小括號里使用var定義了一個臨時變量i,同樣的的,在 for循環結束以后,在外部訪問該變量,也成功返回了相應的值。

以上兩個例子,都是因為JavaScript沒有塊級作用域引起的,所以有時會因為這種情況,導致一些不必要的麻煩。在ES6中,出現了使用 let 和 const聲明變量的方式,來解決了JavaScript中沒有塊級作用域的問題。
你們可以看我之前寫的一篇關于let 和 const 聲明變量的文章——還沒有理解let 和 const的用法和區別嗎,幾百字讓你立馬搞懂

四、其他情況

其實,還有一種情況,會影響變量的訪問順序,那就是在聲明變量時,直接給一個未聲明的變量賦值,例如這樣

?
1
2
3
4
5
6
function fn() {
    sum = 1 + 2
}
fn()
 
console.log(sum)   //返回 3

按照我們本文前面講解的作用域鏈的知識,當執行到最后一局代碼時,此時處于全局執行環境中,查詢不到變量 sum,所以應當會報錯 undefined,但這里卻返回了 3。

這是因為,在我們使用var聲明變量時,會自動將該變量放到離該代碼最近的活動變量中去,也就是函數fn的活動變量中,所以在全局執行環境中的代碼就無法訪問到該變量。但是如果不使用var,而是像這個例子中一樣,直接給一個未定義的變量賦值,這時會自動地將該變量放到全局的活動變量中去,這就是導致本例中在全局環境中還能訪問到變量sum的原因。

五、總結

  1. 作用域鏈可以看成是將變量對象按順序連接起來的一根鏈子
  2. 每個執行環境中的作用域鏈都是不同的
  3. 當我們引用變量時,會順著當前執行環境的作用域鏈,從作用域鏈的開頭開始依次往下尋找對應的變量,直到找到作用域鏈的尾部,報錯undefined
  4. 作用域鏈保證了變量的有序訪問

結束語

好了,對于作用域鏈的講解就到這里了,相信這下大家對JavaScript中的作用域鏈有了很深的理解了吧,我相信,理解了這個概念,可以消除我們代碼中大部分沒必要的BUG。

到此這篇關于JavaScript中作用域鏈的概念及用途講解的文章就介紹到這了,更多相關JavaScript中作用域鏈內容請搜索服務器之家以前的文章或繼續瀏覽下面的相關文章希望大家以后多多支持服務器之家!

原文鏈接:https://blog.csdn.net/l_ppp/article/details/106841716

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 亚洲精品私拍国产福利在线 | japanesqirl日本护士 | 男人与雌性宠物交啪啪小说 | 欧美日韩国产精品va | 国产精品一区久久精品 | 国产日韩综合 | 亚洲国产精品综合欧美 | 国产福利资源网在线观看 | 免费我看视频在线观看 | 成年人视频免费在线播放 | 超兴奋朋友的中文字幕下 | 午夜电影三级还珠格格 | 双性肉文h | 成人尤物 | 逼123| 99热视频| 精品国产免费一区二区三区 | 色狠狠色狠狠综合天天 | 精品国产麻豆免费人成网站 | 亚洲精品卡一卡2卡3卡4卡 | 大肥臀风间由美 中文字幕 大东北chinesexxxx露脸 | 国产福利一区二区三区四区 | 糖心vlog视频永久破解版 | 女性性色生活片免费观看 | 成人免费影 | 9总探花新品牛仔背带裤 | 国内交换一区二区三区 | 日本一区二区高清免费不卡 | 日本免费一区二区三区四区五六区 | 国产欧美日韩综合二区三区 | 91外围 | 国产亚洲欧美一区二区三区 | 亚洲精品国产乱码AV在线观看 | 女人zooxx禽交 | 天堂8在线天堂资源在线 | 日本精品www色 | japonensis中国东北老人 | 欧美交换乱理伦片120秒 | 国产成人夜色影视视频 | 魔兽官方小说 | 男人和女人全黄一级毛片 |