你不知道JavaScript--做用域、LHS查詢和RHS查詢

一、編譯原理
Javascript程序中的一段代碼在執行以前經歷三個步驟,統稱爲「編譯」。
(1)分詞/詞法分析
(2)解析/語法分析
(3)代碼生成
二、LHS查詢和RHS查詢
LHS和RHS的含義是「賦值操做的左側或右側」並不必定意味着就是「 =賦值操做符的左側或右側」。
當變量出如今賦值操做的左側時進行LHS查詢,出如今賦值操做的右側時進行RHS查詢
RHS查詢與簡單地查找某個變量的值別無二致,而LHS查詢則是試圖找到變量的容器自己,從而能夠對其賦值。
若是查找目的是對變量進行賦值,那麼就使用LHS查詢;若是目的是獲取變量的值,就會使用RHS查詢。
考慮如下代碼:
console.log(a)
其中對a的引用是一個RHS引用,由於這裏a並無賦予任何值。相應的,須要查找並取得a的值,這樣才能將值傳給console.log(…).
相比之下,例如:
a=2
這裏對 a 的引用則是 LHS 引用,由於實際上咱們並不關心當前的值是什麼,只是想要爲 =2 這個賦值操做找到一個目標。
考慮下面的程序,其中既有 LHS 也有 RHS 引用:
function foo(a){
  console.log(a);//2
}
foo(2);
最後一行 foo(..) 函數的調用須要對 foo 進行 RHS 引用,意味着「去找到 foo 的值,並把它給我」。而且 (..) 意味着 foo 的值須要被執行,所以它最好真的是一個函數類型的值。
代碼中隱式的 a=2 操做可能很容易被忽略掉。這個操做發生在 2 被看成參數傳遞給foo(..) 函數時, 2 會被分配給參數 a 。爲了給參數 a (隱式地)分配值,須要進行一次LHS 查詢。
這裏還有對 a 進行的 RHS 引用,而且將獲得的值傳給了 console.log(..) 。 console.log(..) 自己也須要一個引用才能執行,所以會對 console 對象進行 RHS 查詢,而且檢查獲得的值中是否有一個叫做 log 的方法。
三、做用域嵌套
當一個塊或函數嵌套在另外一個塊或函數中時,就發生了做用域的嵌套。遍歷嵌套做用域鏈的規則很簡單:引擎從當前的執行做用域開始查找變量,若是找不到,就向上一級繼續查找。當抵達最外層的全局做用域時,不管找到仍是沒找到,查找過程都會中止。
四、 異常
由於在變量尚未聲明(在任何做用域中都沒法找到該變量)的狀況下,這兩種查詢的行爲是不同的。
考慮以下代碼:
function foo(a) {
  console.log( a + b );
  b = a;
}
foo( 2 );
報錯:Uncaught ReferenceError: b is not defined
‘b=a’不是變量聲明,預編譯過程當中不會將其提早
第一次對b進行RHS查詢時是沒法找到改變量,也就是說,這是一個「未聲明」的變量,由於在任何相關的做用域中都沒法找到它。
若是 RHS 查詢在全部嵌套的做用域中遍尋不到所需的變量,引擎就會拋出 ReferenceError異常。值得注意的是, ReferenceError 是很是重要的異常類型。
相關文章
相關標籤/搜索