js中的左查詢和右查詢
阿新 • • 發佈:2019-02-07
值與引用
作用域
- 狹義上說作用域就是一個物件(更確切的來說應該是集合);
- 廣義上來說作用域是一套用來儲存變數,並且之後可以方便的找到這些變數的規則;
- 作用域負責收集並維護由所有宣告的識別符號組成的一系列查詢,並實施一套非常嚴格的規則,確定當前執行的程式碼對這些識別符號的訪問許可權。
上下文
- 程式碼(全域性程式碼,函式體,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(){ //功能程式碼 } }