JavaScript-作用域、塊級作用域、上下文、執行上下文、作用域鏈

JavaScript-作用域、塊級作用域、上下文、執行上下文、作用域鏈

一、作用域

在JavaScript中,作用域(scope,或譯有效範圍)就是變量和函數的可訪問範圍,即作用域控制著變量和函數的可見性生命週期

二、全局/局部作用域

2.1全局作用域(GlobalScope)

(1)不在任何函數內定義的變量就具有全局作用域。

(2)實際上,JavaScript默認有一個全局對象window,全局作用域的變量實際上被綁定到window的一個屬性

JavaScript-作用域、塊級作用域、上下文、執行上下文、作用域鏈

(3)window對象的內置屬性都擁有全局作用域,例如window.name、window.location、window.top等。

2.2局部作用域(LocalScope)

(1)JavaScript的作用域是通過函數來定義的,在一個函數中定義的變量只對這個函數內部可見,稱為函數(局部)作用域

三、全局/局部變量

變量能夠被定義在局部或者全局作用域,這導致運行時變量的訪問來自不同的作用域

3.1全局變量

(1)在函數定義外聲明的變量是全局變量。

(2)全局變量有全局作用域,它的

值可在整個程序中訪問和修改

(3)如果變量在函數內沒有聲明(沒有使用var關鍵字),該變量為全局變量。

3.2局部變量

(1)在函數定義內聲明的變量是局部變量。

(2)因為局部變量只作用於函數內,所以不同的函數可以使用相同名稱的變量

(3)每當執行函數時,都會創建銷燬該變量,且無法通過函數之外的任何代碼訪問該變量。

(4)函數外無法訪問函數內的變量,函數內卻可以訪問函數外的變量。

四、全局變量

1、在函數定義外聲明的變量是全局變量;全局變量有全局作用域,它的值可在整個程序中訪問和修改

JavaScript-作用域、塊級作用域、上下文、執行上下文、作用域鏈

2、如果變量在函數內沒有聲明(沒有使用var關鍵字),該變量為全局變量。

JavaScript-作用域、塊級作用域、上下文、執行上下文、作用域鏈

五、局部變量

1、因為局部變量只作用於函數內,所以不同的函數可以使用相同名稱的變量

JavaScript-作用域、塊級作用域、上下文、執行上下文、作用域鏈

2、每當執行函數時,都會創建銷燬該變量,且無法通過函數之外的任何代碼訪問該變量。

JavaScript-作用域、塊級作用域、上下文、執行上下文、作用域鏈

3、函數外無法訪問函數內的變量,函數內卻可以訪問函數外的變量。

JavaScript-作用域、塊級作用域、上下文、執行上下文、作用域鏈

六、塊級作用域

6.1概念

塊級作用域指在If語句,switch語句,循環語句等語句塊中定義變量,這意味著變量不能在語句塊之外被訪問

6.2var 不支持塊級作用域

(1)在If等語句塊中,定義的變量從屬於該塊所在的作用域,和函數不同,他們不會創建新的作用域。

JavaScript-作用域、塊級作用域、上下文、執行上下文、作用域鏈

6.3let和const

(1)為了解決塊級作用域,ES6引入了let

const關鍵字,可以聲明一個塊級作用域的變量

JavaScript-作用域、塊級作用域、上下文、執行上下文、作用域鏈

(2)全局作用域的生存週期與上述應用相同。局部作用域只在該函數調用執行期間存在。

七、上下文vs作用域

(1)首先需要說明的是

上下文和作用域是不同的概念

(2)每個函數調用都有與之相關的作用域和上下文。從根本上說,作用域是基於函數,而上下文是基於對象

(3)作用域是和每次函數調用時變量的訪問有關,並且每次調用都是獨立的。上下文總是關鍵字this的值,是調用當前可執行代碼的對象的引用。

八、“this”上下文

(1)上下文通常是取決於一個函數如何被調用。當函數作為對象的方法被調用時,this指向調用方法的對象

JavaScript-作用域、塊級作用域、上下文、執行上下文、作用域鏈

(2)當調用一個函數時,通過new操作符創建一個對象的實例,當以這種方式調用時,this指向新創建的實例

JavaScript-作用域、塊級作用域、上下文、執行上下文、作用域鏈

(3)當調用一個未綁定函數,this默認指向全局上下文

或者瀏覽器中的window對象。然而如果函數在嚴格模式下被執行(“usestrict”),this默認指向undefined

九、執行上下文

(1)當函數執行時,會創建一個稱為執行上下文的內部對象(可理解為作用域,不是前面討論的上下文)。一個執行上下文定義了一個函數執行時的環境

(2)函數每次執行時對應的執行上下文都是獨一無二的,所以多次調用一個函數會導致創建多個執行上下文。

(3)當javascript代碼文件被瀏覽器載入後,默認最先進入的是一個全局的執行上下文。當在全局上下文中調用執行一個函數時,程序流就進入該被調用函數內,此時引擎就會為該函數創建一個新的執行上下文

,並且將其壓入到執行棧頂部(作用域鏈)。瀏覽器總是執行位於執行棧頂部的當前執行上下文,一旦執行完畢,該執行上下文就會從執行棧頂部彈出,並且控制權將進入其下的執行上下文。這樣,執行棧中的執行上下文就會被依次執行並且彈出,直到回到全局的執行上下文。

十、作用域鏈

(1)在JavaScript中,函數也是對象,對象中有些屬性我們可以訪問,但有些不可以(訪問),這些屬性僅供JavaScript引擎存取,**[[scope]]**就是其中一個。

(2)[[scope]]指的就是我們所說的作用域,其中存儲了執行上下文的集合。

(3)[[scope]]中所存儲的執行上下文對象的集合,這個集合呈鏈式鏈接,我們把這種鏈式鏈接叫做作用域鏈。

10.1示例

JavaScript-作用域、塊級作用域、上下文、執行上下文、作用域鏈

(1)運行示例代碼將會導致嵌套的函數被從上倒下執行,一直到fourth函數,此時作用域鏈從上到下為:fourth,third, second, first, global。

(2)fourth函數能夠訪問全局變量和任何定義在first,second和third函數中的變量

(和訪問自己的變量一樣)。

(3)一旦fourth函數執行完成,其就會從作用域鏈頂部移除,並且執行權會返回到third函數。這個過程一直持續到所有代碼完成執行。

10.2攀爬作用域鏈

(1)當不同執行上下文之間存在變量命名衝突,可以通過攀爬作用域鏈解決(從頂部到底部)。這也就是說在最內層函數(執行棧頂部的執行上下文)中,具有相同變量名稱的變量將具有較高優先級。

(2)簡單的說,每次試圖訪問函數執行上下文中的變量時,查找進程總是從自己的變量對象開始。如果在自己的變量對象中沒發現要查找的變量,繼續搜索作用域鏈。他將攀爬作用域鏈檢查每一個執行上下文的變量對象,去尋找和變量名稱匹配的值

JavaScript-作用域、塊級作用域、上下文、執行上下文、作用域鏈


分享到:


相關文章: