16.js的執行環境和作用域

執行環境和作用域
    ***********精髓*************
    當ECMAScript開始執行時,創建一個全局執行環境和全局變量對象;後面每次進入一個函數時(這個函數被調用),則創建一個當前函數的執行環境並壓入棧,同時創建此執行環境的變量對象和作用域鏈,作用域鏈的創建規則是複製上一層環境的作用域鏈,並將指向本環境變量對象的指針放到鏈首;離開函數時,從棧中彈出此執行環境並銷燬,同時銷燬環境的變量對象和作用域鏈。
    “當ECMAScript開始執行時,創建一個全局執行環境;每次進入一個函數時(這個函數被調用),則創建一個當前函數的執行環境並壓入棧,離開此函數時從棧中彈出此執行環境並銷燬。”   ----ECMAScript
    “每一個執行環境有一個與其相關的變量對象,變量對象記錄了此執行環境中定義的變量及函數。”    ----ECMAScript
    ************詳解************
    一、執行環境(exection context,也有稱之爲執行上下文)
        所有 JavaScript 代碼都是在一個執行環境中被執行的。執行環境是一個概念,一種機制,用來完成JavaScript運行時在作用域、生存期等方面的處理,它定義了變量或函數是否有權訪問其他數據,決定各自行爲。
        在javascript中,可執行的JavaScript代碼分三種類型:
            1. Global Code(全局代碼),即全局的、不在任何函數裏面的代碼,例如:一個js文件、嵌入在HTML頁面中的js代碼等。
            2. Eval Code(Eval代碼),即使用eval()函數動態執行的JS代碼。
            3. Function Code(函數代碼),即用戶自定義函數中的函數體JS代碼。
        不同類型的JavaScript代碼具有不同的執行環境,這裏我們不考慮evel code,對應於global code和function code存在2種執行環境:全局執行環境和函數執行環境。
        “當ECMAScript開始執行時,創建一個全局執行環境;每次進入一個函數時(這個函數被調用),則創建一個當前函數的執行環境並壓入棧,離開此函數時從棧中彈出此執行環境並銷燬。”   ----ECMAScript
        在一個頁面中,第一次載入JS代碼時創建一個全局執行環境,全局執行環境是最外圍的執行環境,在Web瀏覽器中,全局執行環境被認爲是window對象。因此,所有的全局變量和函數都是作爲window對象的屬性和方法創建的。

        當調用一個 JavaScript 函數時,該函數就會進入與該函數相對應的執行環境。如果又調用了另外一個函數(或者遞歸地調用同一個函數),則又會創建一個新的執行環境,並且在函數調用期間執行過程都處於該環境中。當調用的函數返回後,執行過程會返回原始執行環境。因而,運行中的 JavaScript 代碼就構成了一個執行環境棧。
        “每一個執行環境有一個與其相關的變量對象,變量對象記錄了此執行環境中定義的變量及函數。”    ----ECMAScript
        程序在進入每個執行環境的時候,JavaScript引擎在內部創建一個對象,叫做變量對象(Variable Object)。對應函數的每一個參數,在Variable Object上添加一個屬性,屬性的名字、值與參數的名字、值相同。函數中每聲明一個變量,也會在Variable Object上添加一個屬性,名字就是變量名,因此爲變量賦值就是給Variable Object對應的屬性賦值。在函數中訪問參數或者局部變量時,就是在variable Object上搜索相應的屬性,返回其值。(另外注意:一般情況下Variable Object是一個內部對象,JS代碼中無法直接訪問。規範中對其實現方式也不做要求,因此它可能只是引擎內部的一種數據結構。)

    二、Scope/Scope Chain(作用域/作用域鏈)
        
        function Fn1(){
            function Fn2(){
                alert(document.body.tagName);//BODY
                //other code...
            }
            Fn2();
        }
        Fn1();
        //code here
        當代碼在一個環境中執行時,都會創建基於Variable Object的一個作用域鏈。 作用域鏈的用途是保證對執行環境有權訪問的所有變量和函數的有序訪問。整個作用域鏈是由不同執行位置上的Variable Object按照規則所構建一個鏈表。作用域鏈的最前端,始終是當前正在執行的代碼所在環境的Variable Object。如果這個環境是函數(比如Fn2),則將其活動對象(activation object)作爲變量對象。活動對象在最開始時只包含一個變量,就是函數內部的arguments對象。作用域鏈中的下一個Variable Object來自該函數(Fn2)的包含環境(也就是Fn1),而再下一個Variable object來自再下一個包含環境。這樣,一直延續到全局執行環境,全局執行環境的Variable Object始終是作用域鏈中的最後一個對象。

        如上所述,作用域鏈感覺就是一個Variable Object鏈表,當訪問一個變量時,先在鏈表的第一個Variable Object(最前端)上查找,如果沒有找到則繼續在第二個Variable Object上查找,直到搜索結束,也就是搜索到全局執行環境的Variable Object中。這也就形成了Scope Chain的概念。
發佈了35 篇原創文章 · 獲贊 4 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章