1. 程式人生 > >一、作用域是什麼 (學習筆記)—— 《你不知道的JavaScript》

一、作用域是什麼 (學習筆記)—— 《你不知道的JavaScript》

因為全部都是文字不太好理解,所以儘可能地把所有的文字都畫成了圖,便於理解。

作用域是什麼

傳統編譯流程:

JavaScript 引擎會在語法分析和程式碼生成階段,通過特定的步驟,對執行效能進行優化。包括冗餘元素優化等。

JavaScript 編譯,大部分情況下,發生在程式碼執行前的幾微妙(甚至更短)。

理解作用域

引擎、編譯器、作用域

var a = 1;

以上程式碼,經歷了兩個不同的宣告:

  • 編譯器在編譯時的處理
  • 引擎在執行時的處理

 以 var a = 1; 為例,演示引擎、編譯器、作用域三者是如何工作的

變數的賦值操作會執行兩個動作:1. 編譯器在當前作用域中宣告一個變數; 2. 執行時引擎在作用域中查詢該變數,找到便賦值,找不到丟擲異常。

LHS && RHS

先來張圖,解釋什麼是 LHS、RHS

看下面程式碼,加深理解

console.log(a); // 對 a 的引用是 RHS 引用。因為沒有對 a 賦值,而是查詢並取得 a 的值。
a = 2; // 對 a 的引用是 LHS 引用。不用關心 a 的值是什麼,只需要為 = 2 這個賦值操作找到一個目標。

引擎和作用域的對話

以下面程式碼為例:

function foo(a) {
    console.log(a);
}
foo(2);

小測驗

把自己當做引擎,同作用域進行一次“對話”。

function foo(a) {
    var
b = a; return a + b; } var c = foo(2);

1. 找到其中所有的LHS查詢。(這裡有3處!)

2. 找到其中所有的RHS查詢。(這裡有4處!)

作用域巢狀

當一個塊或函式巢狀在另一個塊或函式中時,就發生了作用域巢狀。因此,在當前作用域中無法找到該變數時,引擎會在當前巢狀的作用域的外層繼續查詢,直到找到該變數,或抵達最外層作用域(全域性作用域為止)。

看以下程式碼:

function foo(a) {
    return a + b;
}

var b = 1;
foo(2);

對 b 進行的 RHS 引用無法在函式 foo 內部完成,但可以在上一級作用域(在這個例子中就 是全域性作用域)中完成。

我們來模擬一下以上程式碼的引擎與作用域的對話。

注:以上所有的文字、程式碼都是本人一個字一個字敲上去的,圖片也是一張一張畫出來的,轉載請註明出處,謝謝!