關(guān)于JS管理作用域的問(wèn)題
理解JavaScript如何管理作用域和作用域鏈很重要。因?yàn)樵谧饔糜蜴溨幸檎业淖兞繉?duì)象的個(gè)數(shù)直接影響標(biāo)識(shí)符解析的性能。標(biāo)識(shí)符在作用域鏈中的位置越深,查找和訪問(wèn)它所需的時(shí)間越長(zhǎng);如果作用域管理不當(dāng),就會(huì)給腳本的執(zhí)行時(shí)間帶來(lái)負(fù)面影響。
當(dāng)執(zhí)行JavaScript代碼時(shí),JavaScript引擎會(huì)創(chuàng)建一個(gè)執(zhí)行上下文(Execution Context)。執(zhí)行上下文(有時(shí)被稱(chēng)為作用域)設(shè)定了代碼執(zhí)行時(shí)所處的環(huán)境。JavaScript引擎會(huì)在頁(yè)面加載后創(chuàng)建一個(gè)全局的執(zhí)行上下文,然后每執(zhí)行一個(gè)函數(shù)時(shí)都會(huì)創(chuàng)建一個(gè)對(duì)應(yīng)的執(zhí)行上下文,最終建立一個(gè)執(zhí)行上下文的堆棧,當(dāng)前起作用的執(zhí)行上下文在堆棧的最頂端。
每個(gè)執(zhí)行上下文都有一個(gè)與之關(guān)聯(lián)的作用域鏈,用于解析標(biāo)識(shí)符。作用域鏈包含一個(gè)或多個(gè)變量對(duì)象,這些對(duì)象定義了執(zhí)行上下文作用域內(nèi)的標(biāo)識(shí)符。全局執(zhí)行上下文的作用域鏈中只有一個(gè)變量對(duì)象,它定義了JavaScript中所有可用的全局變量和函數(shù)。當(dāng)函數(shù)被創(chuàng)建(不是執(zhí)行)時(shí),JavaScript引擎會(huì)把創(chuàng)建時(shí)執(zhí)行上下文的作用域鏈賦給函數(shù)的內(nèi)部屬性[[Scope]]。然后,當(dāng)函數(shù)被執(zhí)行時(shí),JavaScript引擎會(huì)創(chuàng)建一個(gè)活動(dòng)對(duì)象(Activetion Object),并在初始化時(shí)給this、arguments、命名參數(shù)和該函數(shù)的所有局部變量賦值?;顒?dòng)對(duì)象會(huì)出現(xiàn)在執(zhí)行上下文作用域鏈的頂端,緊接其后的是函數(shù)[[scope]]屬性中的對(duì)象。
在執(zhí)行代碼時(shí),JavaScript引擎通過(guò)搜索執(zhí)行上下文的作用域鏈來(lái)解析諸如變量和函數(shù)名這樣的標(biāo)識(shí)符。解析標(biāo)識(shí)符的過(guò)程從作用域的頂端開(kāi)始,按照自上而下的順序進(jìn)行。
驗(yàn)證理論function add(num1, num2) {
return num1 + num2;
}
當(dāng)這段代碼執(zhí)行開(kāi)始時(shí),add函數(shù)擁有一個(gè)僅包含全局變量對(duì)象的[[scope]]屬性。如下圖:
在執(zhí)行add函數(shù)時(shí),JavaScript引擎會(huì)創(chuàng)建一個(gè)新的執(zhí)行上下文和一個(gè)包含this、arguments、num1、num2的活動(dòng)對(duì)象,并把活動(dòng)對(duì)象添加到作用域鏈中。在add()函數(shù)內(nèi)部運(yùn)行時(shí),JavaScript引擎需要解析函數(shù)里的num1和num2標(biāo)識(shí)符。var total = add(5, 10);
解析過(guò)程是從作用域鏈中的第一個(gè)對(duì)象開(kāi)始,這個(gè)對(duì)象就是包含該函數(shù)局部變量的活動(dòng)對(duì)象。如果在該對(duì)象中沒(méi)有找到標(biāo)識(shí)符,就會(huì)繼續(xù)在作用域鏈中下一個(gè)對(duì)象里查找標(biāo)識(shí)符。一旦找到標(biāo)識(shí)符,查找就結(jié)束。
高效的數(shù)據(jù)存取局部變量是JavaScript中讀寫(xiě)最快的標(biāo)識(shí)符。
一個(gè)好的經(jīng)驗(yàn):任何非局部變量在函數(shù)中的使用超過(guò)一次時(shí),都應(yīng)該將其存儲(chǔ)為局部變量。
對(duì)于數(shù)組和對(duì)象,始終將那些需要頻繁存取的值存儲(chǔ)到局部變量中。
實(shí)際上每次存取HTMLCollection對(duì)象屬性,都會(huì)對(duì)DOM文檔進(jìn)行動(dòng)態(tài)查詢(xún)。
如果需要對(duì)HTMLCollection對(duì)象的成員反復(fù)存取,高效的方式是將它們復(fù)制到數(shù)組里。
- 詳解JavaScript的AngularJS框架中的作用域與數(shù)據(jù)綁定
- JavaScript的作用域和塊級(jí)作用域概念理解
- 深入理解Javascript中this的作用域
- 深入理解JavaScript高級(jí)之詞法作用域和作用域鏈
- javascript 函數(shù)及作用域總結(jié)介紹
- javascript中的變量作用域以及變量提升詳細(xì)介紹
- 淺析js封裝和作用域
- 深入Javascript函數(shù)、遞歸與閉包(執(zhí)行環(huán)境、變量對(duì)象與作用域鏈)使用詳解
- js作用域及作用域鏈概念理解及使用
- js變量以及其作用域詳解
- js使用函數(shù)綁定技術(shù)改變事件處理程序的作用域
- JavaScript作用域示例詳解
相關(guān)文章
JavaScript中的prototype原型學(xué)習(xí)指南
這篇文章主要介紹了JavaScript中的prototype原型學(xué)習(xí)指南,包括原型鏈與原型繼承等重要知識(shí),需要的朋友可以參考下2016-05-05<script defer> defer 是什么意思
好多朋友不知道 script后面加個(gè)defer是什么意思有什么作用。2009-05-05為JS擴(kuò)展Array.prototype.indexOf引發(fā)的問(wèn)題及解決辦法
這篇文章主要介紹了為JS擴(kuò)展Array.prototype.indexOf引發(fā)的問(wèn)題及解決辦法,需要的朋友可以參考下2015-01-01VB倒計(jì)時(shí)器和JS當(dāng)前時(shí)間
VB倒計(jì)時(shí)器和JS當(dāng)前時(shí)間...2006-11-11typescript常見(jiàn)高級(jí)技巧總結(jié)
這篇文章主要介紹了typescript常見(jiàn)高級(jí)技巧總結(jié),需要的朋友可以參考下2022-10-10