1. 程式人生 > 其它 >js的執行環境與作用域

js的執行環境與作用域

技術標籤:ES6/ES5

4、執行環境與作用域

  • 變數或函式的上下文決定了它們可以訪問哪些資料,以及它們的行為。每個上下文都有一個關聯的變數物件(variable object),而這個上下文中定義的所有變數和函式都存在於這個物件上。
  • 全域性上下文是最外層的上下文。在瀏覽器中,全域性上下文就是我們常說的 window 物件,因此所有通過var 定義的全域性變數和函式都會成為 window 物件的屬性和方法。使用 let 和 const 的頂級宣告不會定義在全域性上下文中,但在作用域鏈解析上效果是一樣的。上下文在其所有程式碼都執行完畢後會被銷燬,包括定義在它上面的所有變數和函式(全域性上下文在應用程式退出前才會被銷燬,比如關閉網頁或退出瀏覽器)。
var person = 'lisa';
console.log(window.person) // lisa

const person2 = 'lily';
console.log(window.person2) //ERROR 報錯
  • 每個函式呼叫都有自己的上下文。當代碼執行流進入函式時,函式的上下文被推到一個上下文棧上。在函式執行完之後,上下文棧會彈出該函式上下文,將控制權返還給之前的執行上下文。ECMAScript程式的執行流就是通過這個上下文棧進行控制的。
  • 上下文中的程式碼在執行的時候,會建立變數物件的一個作用域鏈(scope chain)。這個作用域鏈決定了各級上下文中的程式碼在訪問變數和函式時的順序。程式碼正在執行的上下文的變數物件始終位於作用域鏈的最前端。如果上下文是函式,則其活動物件(activationobject)用作變數物件。活動物件最初只有一個定義變數:arguments 。(全域性上下文中沒有這個變數。)作用域鏈中的下一個變數物件來自包含上下文,再下一個物件來自再下一個包含上下
    文。以此類推直至全域性上下文;全域性上下文的變數物件始終是作用域鏈的最後一個變數物件。
  • 程式碼執行時的識別符號解析是通過沿作用域鏈逐級搜尋識別符號名稱完成的。搜尋過程始終從作用域鏈的最前端開始,然後逐級往後,直到找到識別符號。(如果沒有找到識別符號,那麼通常會報錯。)
var color = "blue";

function changeColor() {
    if (color === "blue") {
        color = "red";
    } else {
        color = "blue"
; } } changeColor(); console.log(color) // 'red'
  • 對這個例子而言,函式 changeColor() 的作用域鏈包含兩個
    物件:一個是它自己的變數物件(就是定義 arguments 物件的那
    個),另一個是全域性上下文的變數物件。這個函式內部之所以能夠訪
    問變數 color ,就是因為可以在作用域鏈中找到它。
 color = "blue";

function changeColor() {
    let anotherColor = "red";

    function swapColors() {
        let tempColor = anotherColor;
        anotherColor = color;
        color = tempColor;
        console.info("tempColor",tempColor) //red
        console.info("anotherColor",anotherColor) // blue
        console.info("color",color) // red
        // 這裡可以訪問color、anotherColor和tempColor
    }
    // 這裡可以訪問color和anotherColor,但訪問不到tempColor
    swapColors();
}
// 這裡只能訪問color
changeColor();
  • 內部上下文可以通過作用域鏈
    訪問外部上下文中的一切,但外部上下文無法訪問內部上下文中的任
    何東西。上下文之間的連線是線性的、有序的。每個上下文都可以到
    上一級上下文中去搜索變數和函式,但任何上下文都不能到下一級上
    下文中去搜索。

注意 函式引數被認為是當前上下文中的變數,因此也跟上下文中
的其他變數遵循相同的訪問規則。