如今開始講做用域鏈🕺🏼在這篇文章中,我假設您瞭解執行上下文:儘管如此,我也將很快就此發表一篇文章😃javascript
讓咱們看下面的代碼:java
const name = "Lydia"
const age = 21
const city = "San Francisco"
function getPersonInfo() {
const name = "Sarah"
const age = 22
return `${name} is ${age} and lives in ${city}`
}
console.log(getPersonInfo())
複製代碼
咱們調用getPersonInfo函數,該函數返回一個包含name,age,city的值的字符串: Sarah is 22 and lives in San Francisco
。可是getPersonInfo函數不包含名爲city🤨 的變量。它怎麼知道city的?git
首先,爲不一樣的上下文設置存儲空間。咱們有默認的全局上下文
(在瀏覽器中是window
,在Node中是 global
),以及getPersonInfo的局部上下文
。每一個上下文也都有一個做用域鏈
。github
對於getPersonInfo來講,做用域鏈看起來像這樣(看不懂?不用擔憂,下面會講):瀏覽器
做用域鏈是對對象的「引用鏈」,這些對象包含對在該執行上下文中可引用的值(和其餘做用域)。(⛓:「嘿,這些都是您能夠在此上下文中引用的全部值」。)做用域鏈是在建立執行上下文時建立的,這意味着它是在運行時建立的!函數
可是,在本文中,我通常不會討論活動對象
或執行上下文,咱們只關注做用域!在如下示例中,執行上下文中的鍵/值對錶示做用域鏈對變量的引用。oop
全局執行上下文的做用域鏈引用了3個變量:name
的值是Lydia,age
的值是21,city
的值是San Francisco。在本地上下文中,咱們引用了2個變量:name
的值是Sarah和age
的值是22。post
當咱們嘗試訪問getPersonInfo函數中的變量時,引擎首先檢查本地做用域鏈。ui
本地做用域鏈引用了name和age!name的值爲Sarah,age的值爲22。可是如今,當它嘗試訪問city時會發生什麼?spa
爲了找到city的值,引擎「沿做用域鏈往下」。這意味着引擎不會輕易放棄:它會努力爲您查看是否能夠city在本地做用域引用的外部做用域(在本例中爲全局對象)中找到變量的值。
在全局上下文中,咱們聲明瞭變量city,它的值爲San Francisco
,所以引用了變量city。如今咱們有了變量的值,函數getPersonInfo能夠返回字符串Sarah is 22 and lives in San Francisco
🎉
咱們能夠順着做用域鏈向下,但咱們順着做用域鏈向上。(好吧,這可能會使人困惑,由於有些人說的是向上而不是向下,因此我要改寫:您可使用外部做用域,但不能進入內部做用域。我想用瀑布形象地表示這一點
甚至更深:
讓咱們以這段代碼爲例。
幾乎同樣,可是有一個很大的不一樣:咱們如今僅在getPersonInfo函數中聲明city,而不是在全局範圍中聲明。咱們沒有調用getPersonInfo函數,所以也沒有建立本地上下文。然而,咱們試圖在全局做用域訪問name,age,city。
它拋出ReferenceError!在全局做用域內它找不到一個叫作city的變量,而且沒有外部做用域,而且它不能沿着做用域鏈向上。
這樣,您能夠利用做用域來「保護」變量或者從新使用變量。
除了全局和局部做用域外,還有一個塊做用域
。用let 或 const關鍵字聲明的變量的做用域爲最接近的大括號({})。
const age = 21
function checkAge() {
if (age < 21) {
const message = "You cannot drink!"
return message
} else {
const message = "You can drink!"
return message
}
}
複製代碼
您能夠將範圍可視化爲:
咱們有一個全局做用域,一個函數做用域和兩個塊做用域。因爲message用大括號括起來,所以咱們可以對變量進行兩次聲明。
快速回顧:
範圍(鏈)就是這樣!關於這一點,還有不少話要說,因此我會在空閒時間添加一些額外的信息。若是您遇到任何困難,請隨時提出問題,我很樂意提供幫助!💕
本系列包括6篇文章