1. 程式人生 > >js中的左查詢和右查詢

js中的左查詢和右查詢

值與引用

作用域

  • 狹義上說作用域就是一個物件(更確切的來說應該是集合);
  • 廣義上來說作用域是一套用來儲存變數,並且之後可以方便的找到這些變數的規則;
    • 作用域負責收集並維護由所有宣告的識別符號組成的一系列查詢,並實施一套非常嚴格的規則,確定當前執行的程式碼對這些識別符號的訪問許可權。

上下文

  • 程式碼(全域性程式碼,函式體,eval程式碼)執行前的準備工作:
    • 1.提升(變數 函式 函式表示式);
    • 2.確定this指向;
    • 3.與對應作用域關聯;
    • 如果程式碼段是函式體,那麼在此基礎上需要附加:引數 賦值,arguments 賦值;
  • 作用域與執行上下文環境的關係:
    • 一個作用域下可能包含若干個上下文環境。有可能從來沒有過上下文環境(函式從來就沒有被呼叫過); 有可能有過,現在函式被呼叫完畢後,上下文環境被銷燬了;

左/右查詢

  • 左查詢:

    • 賦值符號的左側,賦值操作的目標是誰;
    • 函式呼叫時實參與形參的關係就是一次左查詢;
    • 對等號左邊變數的查詢。在整條作用域鏈中,如果沒有找到變數的宣告,js引擎會自動在全域性宣告一個同名變數;但是這個變數的宣告是不會提升的。
      (function(){
          function test(a){
              b=a;
              console.log(b);//2
          }
          test(2);
      })();
      console.log(b);//2
  • 右查詢:

    • 賦值符號的非左側,誰是賦值操作的源頭;
    • 對等號非左邊變數的查詢。在整條作用域鏈中,如果沒有找到變數的宣告 直接拋ReferenceError錯誤;

      console.log(a);//ReferenceError: a is not defined
    • 特殊的右查詢

      //a並未定義賦值
      console.log(typeof a);//undefined
  • 嚴格模式&非嚴格模式

    • 在變數還沒有宣告(在任何作用域中都無法找到該變數)的情況下,這兩種查詢的行為是不一樣的
    • 非嚴格模式:
      • 右查詢在查詢所有的巢狀作用域中遍尋不到所需的變數,引擎就會丟擲ReferenceError異常,但需要注意typeof時不會報異常;
      • 左查詢在查詢所有的巢狀作用域中遍尋不到所需的變數,全域性作用域中就會建立一個具有該名稱的變數;
    • 嚴格模式:
      • RHS,LHS都會丟擲ReferenceError異常
      • ReferenceError異常同作用域判別失敗相關,TypeError則代表作用域判別成功了,但對結果的操作是非法或不合理的;
  • typeof的安全防範機制

    • 1.在程式中使用全域性變數DEBUG作為“除錯模式”開關,我們在DEBUG.js檔案的宣告var DEBUG =true;該檔案只在開發和測試時才被載入到瀏覽器,在生產環境中不予載入;

      if(DEBUG){ //在生產環境中會報錯
               console.log("開始除錯");
        }
      
        if(typeof DEBUG !== "undefined"){
                console.log("開始除錯");    
        }
    • 2.為某個缺失的功能寫polyfill(襯墊程式碼,用來補充當前執行環境中缺失的功能)

      if(typeof polyfill_a === "undefined"){
              //注意這一塊不需要var,跟變數的提升有關
                 //這一塊需要使用函式表示式而不是函式宣告
                 polyfill_a = function(){
                    //功能程式碼
                 }
         }