
前言
為可以大概了解作用域鏈?zhǔn)莻€什么東西,本文著重說明作用域鏈,盡量不引入其他的概念。
變量對象
在說作用域鏈前,先簡單地說明變量對象,畢竟是作用域鏈的核心組成。每個函數(shù)內(nèi)部都會定義變量,會定義函數(shù),在全局環(huán)境下也會定義函數(shù)、變量。對應(yīng)的區(qū)域都會有一個特殊對象,這個對象就會存放對應(yīng)區(qū)域的變量、函數(shù),這個特殊的對象就是變量對象。所以說全局環(huán)境有和全局環(huán)境對應(yīng)的變量對象,每個函數(shù)內(nèi)部也有一個與之對應(yīng)的變量對象,不如下面的代碼:
<script>
var a = 1;
var b = [1, 2, 3, 4, 5];
function fn(isShow){
var gihubLink = 'https://github.com/issaxite';
if(isShow) {
console.log(githubLink);
} else {
console.log('issax');
}
}
</script>
上面的代碼中,
- 全局環(huán)境的變量對象存儲的是:a, b, fn
- fn函數(shù)的變量對象存儲的是:isShow,gihubLink;你可以看見,fn函數(shù)的變量對象沒有包含全局環(huán)境定義的變量和函數(shù)
作用域鏈
為什么要說變量對象呢?因為作用域鏈就是由變量對象組成,作用域鏈?zhǔn)且粋€由變量對象組成的列表,一個有序,只能由頭開始逐個往尾訪問的列表(說是列表其實更應(yīng)該說是鏈表,先不要在意這個概念)。
并且作用域鏈和變量對象有一個共同的特點:每個區(qū)域都會有一個與之對象對的。比如說上面的代碼中,全局環(huán)境有一個與之對應(yīng)的變量對象,也有一個和全局環(huán)境對應(yīng)的作用域鏈;fn函數(shù)也是如此。
那么作用域鏈?zhǔn)怯心男┳兞繉ο蠼M成呢?
我們先看下圖:

由上圖應(yīng)該可以看出,作用域鏈由當(dāng)前區(qū)域的變量對象作為開頭,然后是逐層往外直至全局環(huán)境的變量對象組成如上圖一樣的列表,這就是作用域鏈,并且如上文所說,每個區(qū)域都有這樣一個與之對應(yīng)的作用域鏈。比如下面的代碼:
<script>
var a = 1;
var b = [1, 2, 3, 4, 5];
function fn(isShow){
var gihubLink = 'https://github.com/issaxite';
function fn1(param1, param2){
var mailLink = 'issaxite@gmail.com';
}
}
</script>
-
fn1函數(shù)的作用域鏈:
-
fn的作用域鏈:
-
全局環(huán)境的作用域鏈
那么作用域鏈的作用是什么?
jser都應(yīng)該有這樣的體驗,在函數(shù)內(nèi)部可以訪問到外部區(qū)域的變量和函數(shù),而在外部區(qū)域訪問不了函數(shù)內(nèi)定義的變量:
<script>
var a = 1;
var b = 2;
function fn(){
var c = 3;
console.log(a, b, c)
}
console.log(c);
</script>

如上所示,fn函數(shù)內(nèi)部可以訪問到外層區(qū)域(全局環(huán)境)的變量,為什么可以,就是因為fn函數(shù)的作用域鏈,在變量調(diào)用的時候(在fn就是訪問c變量的時候),會在當(dāng)前作用域鏈的頭部開始往尾部,依次在變量對象中查詢對應(yīng)的變量,找到即返回,不再繼續(xù)查詢,這個也是內(nèi)層同名變量比外層同名變量優(yōu)先級更高的原因,這個查詢的過程叫做變量解析,也叫標(biāo)識符解析,
console.log(c);會拋出異常就是因為全局環(huán)境的作用域鏈中的變量對象沒有該變量。
結(jié)語
正如本文開頭所說,本文僅是淺析作用域鏈,一些相關(guān)概念都被隱掉了,比如說上文說的“區(qū)域“,應(yīng)該說是作用域或執(zhí)行環(huán)境,這兩個概念其實說的不是很明確,比如說執(zhí)行環(huán)境,在《javascript高級程序設(shè)計》的4.2中有說到,簡直堪稱極具迷惑性,標(biāo)題更加是醉”執(zhí)行環(huán)境和作用域“,然而基本沒有談到作用域。作用域在《javascript權(quán)威指南》的3.10中倒是說的挺多,還分變量作用域和函數(shù)作用域。不過啊,要是拘泥于這些細(xì)節(jié)更加難搞明白作用域鏈了。上文也說道作用域鏈更像鏈表,個人也是這樣認(rèn)為,但兩書中都沒有明確地說是,權(quán)威指南倒是提了一下,而且作用域鏈也是很符合鏈表的特點,如果不了解鏈表,但由不了解其他語言,推薦這本書《數(shù)據(jù)結(jié)構(gòu)與算法JavaScript描述》,吐槽完畢,作用域鏈的解析當(dāng)然沒有那么淺顯,想了解更多細(xì)節(jié)還是自己去看看書。
有說得不對的,歡迎指出


