詞法作用域 VS 動(dòng)態(tài)作用域

Javascript的詞法作用域

作用域是個(gè)語(yǔ)言無(wú)關(guān)的概念,你要接觸過(guò)Lisp或者Scheme等語(yǔ)言,應(yīng)該對(duì)這個(gè)概念會(huì)非常熟悉。我在這篇文章會(huì)介紹詞法作用域和動(dòng)態(tài)作用域的基本知識(shí),讓你剛好對(duì)這個(gè)概念了解,此外,我們還會(huì)討論下JavaScript的詞法作用域。

首先你得明白程序設(shè)計(jì)中作用域這個(gè)概念:通常來(lái)說(shuō),一段程序代碼中所用到的名字并不總是有效/可用的,而限定這個(gè)名字的可用性的代碼范圍就是這個(gè)名字的作用域。

詞法作用域,也叫靜態(tài)作用域,它的作用域是指在詞法分析階段就確定了,不會(huì)改變。動(dòng)態(tài)作用域是在運(yùn)行時(shí)根據(jù)程序的流程信息來(lái)動(dòng)態(tài)確定的,而不是在寫(xiě)代碼時(shí)進(jìn)行靜態(tài)確定的。

我們以下面這段Javascript代碼來(lái)說(shuō)明詞法作用域和動(dòng)態(tài)作用域,但是你要明白,闡述的概念是與Javascript無(wú)關(guān)的。

var a = 2;

function foo() {
  console.log(a); // 會(huì)輸出2還是3?
}

function bar() {
  var a = 3;
  foo();
}

bar();

如果是詞法作用域,它會(huì)讓 foo() 函數(shù)引用到全局作用域中的 a,因此會(huì)輸出 2。我們說(shuō)過(guò),詞法作用域是寫(xiě)代碼的時(shí)候就靜態(tài)確定下來(lái)的。Javascript中的作用域就是詞法作用域(事實(shí)上大部分語(yǔ)言都是基于詞法作用域的),所以這段代碼在瀏覽器中運(yùn)行的結(jié)果是輸出 2

Javascript作用域鏈

而動(dòng)態(tài)作用域并不關(guān)心函數(shù)和作用域是如何聲明以及在何處聲明的,只關(guān)心它們從何處調(diào)用。換句話說(shuō),作用域鏈?zhǔn)腔谡{(diào)用棧的,而不是代碼中的作用域嵌套。因此,如果Javascript具有動(dòng)態(tài)作用域,理論上輸出結(jié)果是 3。

為什么會(huì)這樣?因?yàn)楫?dāng) foo() 無(wú)法找到 a 的變量引用時(shí),會(huì)順著調(diào)用棧在調(diào)用 foo() 的地方查找 a ,而不是在嵌套的詞法作用域鏈中向上查找。由于 foo() 是在 bar() 中調(diào)用的,引擎會(huì)檢查 bar() 的作用域,并在其中找到值為 3 的變量 a。

你可能會(huì)覺(jué)得很奇怪,但這其實(shí)是因?yàn)槟憧赡苤粚?xiě)過(guò)基于詞法作用域的代碼(或者至少以詞法作用域?yàn)榛A(chǔ)進(jìn)行了深入的思考),因此對(duì)動(dòng)態(tài)作用域感到陌生。如果你只用基于動(dòng)態(tài)作用域的語(yǔ)言寫(xiě)過(guò)代碼,就會(huì)覺(jué)得這是很自然的,而詞法作用域看上去才怪怪的。

需要明確的是,Javascript并不具有動(dòng)態(tài)作用域,它只有詞法作用域,簡(jiǎn)單明了。但是,它的 eval()、with、this機(jī)制某種程度上很像動(dòng)態(tài)作用域,使用上要特別注意。

主要區(qū)別:詞法作用域是在寫(xiě)代碼或者定義時(shí)確定的,而動(dòng)態(tài)作用域是在運(yùn)行時(shí)確定的(this也是?。?。詞法作用域關(guān)注函數(shù)在何處聲明,而動(dòng)態(tài)作用域關(guān)注函數(shù)從何處調(diào)用。

參考資料


  1. 書(shū)籍:《你不知道的JavaScript:上卷》
  2. 百度百科詞條:作用域
  3. cnblogs:《淺談靜態(tài)作用域和動(dòng)態(tài)作用域
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容