javascript
javascript感叹号1_「翻译」JavaScript的可视化学习之三:作用域(链)
兒子:爸,我有個愿望,當有一天我疲憊回家時,你打電話告訴我,家里有百億家產等我繼承,之前裝窮都是為了鍛煉我。爸:別著急,爸爸也在等你爺爺的電話呢。- 隨時繼承百億家業的Scope(Chain)
周生生技術:作用域(鏈)概覽圖
請注意上面這張圖,作用域(鏈)的那些事,將在這個圖上緩緩展開。
是時候聊聊作用域鏈了。我假設大家對執行上下文有一些基本認識:后面我會專門寫一篇文章來介紹它。
上代碼:
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`的值的?
首先,不同的上下文都有各自的內存空間。
默認我們有個全局上下文(在瀏覽器里面是window,在Node中是global),還有`getPersonInfo`函數的本地上下文。每個上下文都會有一個自己的作用域鏈。
對于`getPersonInfo`函數,作用域鏈看起來是下面這個樣子(別擔心,目前它可能還不是很好理解):
1、作用域鏈
作用域鏈大體就是一個引用鏈,它指向執行上下文引用的對象(包含別的作用域),它說,嗨,這里就是所有你能夠在這個上下文中使用的變量。作用域鏈在執行上下文創建的時候被創建,這也意味著,它是在運行時被創建的。
但是,我不會在這一章中討論活動對象或者執行上下文,讓我們把火力集中在作用域上!在接下來的例子中,執行上下文中的鍵值對代表了作用域鏈中指向變量的引用。
2、執行上下文的鍵值對
全局執行上下文的作用域鏈有一個引用指向三個變量:值為`Lydia`的`name`,值為`21`的`age`和值為`San Francisco`的`city`。
本地上下文中,我們有一個引用指向兩個變量:值為`Sarah`的`name`和值為`22`的`age`。
當我們在`getPersonInfo`函數中訪問變量時,引擎會首先檢查本地作用域鏈。
3、函數中訪問變量
本地作用域鏈包含指向`name`和`age`的引用!`name` 的值是`Sarah` ,`age` 的值是`22`. 但是,當我們訪問`city`時會發生什么呢?
為了找到`city`的值,引擎“沿著作用域鏈往下找”。這說明引擎不是那么容易放棄的:本地作用域引用了一個變量,因為不是在本地作用域中聲明的,引擎會竭盡全力在外部作用域中去尋找。在這里指的是全局對象。
4、函數中訪問外部變量
在全局上下文中,我們聲明了變量 `city`并賦值`San Francisco`,因此在全局上下文中有變量`city`的引用?,F在我們有值了,函數`getPersonInfo`返回了字符串`Sarah is 22 and lives in San Francisco`。
我們可以順著作用域鏈往下走,但是不能沿著作用域鏈往上走(好吧這里可能會有點迷惑,因為有些人會把下說成上,所以我重新描述一下:你可以走到外部作用域中,但是不能走進內部作用域)。
我喜歡把這個視覺化為一個瀑布模型:
5、作用域鏈的瀑布模型
或者更深一些:
6、作用域鏈的深層瀑布模型
接下來看如下例子:
7、作用域鏈的作用范圍
大體看起來似乎和上面的差不多,但是這里有個很大的區別:我們只在`getPersonInfo`函數中聲明變量`city`,而沒有在全局作用域中聲明。我們沒有調用`getPersonInfo`函數,所以也沒有本地上下文被創建。所以看起來我們打算在全局上下文中訪問變量`name`, `age` 和 `city`。
8、引用錯誤
結果,它拋出了錯誤`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
}
}
你可以把作用域視覺化如下:
9、塊作用域的視覺化
我們有一個全局作用域,一個函數作用域,兩個塊作用域。我們可以聲明變量message兩次,因為它被限制在大括號里頭。
敲黑板劃重點:
- 作用域鏈是引用鏈,指向在當前上下文中引用的變量的值。
- 作用域讓重用低層作用域的變量名變成可能,因為它只能是順著作用域往下,而不是往上走。
這就是作用域(鏈)!它還有很多故事,等我有時間再繼續。如果有疑問請隨時提問,我喜歡助人為樂!
譯者:
原文作者是個可愛的小女孩,所以文章中有很多的感嘆號,經過男性強行修飾后可能有所減少。
翻譯來源:https://dev.to/lydiahallie/javascript-visualized-scope-chain-13pd
總結
以上是生活随笔為你收集整理的javascript感叹号1_「翻译」JavaScript的可视化学习之三:作用域(链)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: jar打包 剔除第三方依赖以及它的依赖_
- 下一篇: word中光标选择一列文字_Word中文