摘要:如果查找的目的是對變量進行賦值,就會使用查詢如果目的是獲取變量的值,就會用查詢。賦值操作會導致查詢。接下來,會查詢查詢變量并對其進行賦值。不成功的引用會導致拋出異常。
簡述編譯原理
JavaScript 程序中的一段源代碼在執行之前會經歷三個步驟,統稱為 編譯
分詞/詞法分析
解析/語法分析
代碼生成
先看原書對一個賦值操作的拆解說明:
變量的賦值操作會執行兩個動作,首先編譯器會在當前作用域中聲明一個變量(如果之前沒有聲明過),然后在運行時引擎會在作用域中查找該變量,如果能夠找到就會對它賦值。 --- 《你不知道的JavaScript(上卷)》 P7
而要講的 LHS 和 RHS 就是上面說的對變量的兩種查找操作,查找的過程是由作用域(詞法作用域)進行協助,在編譯的第二步中執行。
LHS 和 RHS字面意思其實是 Left Hand Side和 Right Hand Side 即左手邊和右手邊
一般可以理解為 賦值操作的左側和右側
先看個例子一console.log(a);
這里對 a 是一個 RHS 引用,因為 a 并沒有賦予任何值,目的是為了取到 a 的值并打印出來。
a = 2;
這里對 a 是一個 LHS 引用,因為實際上我們不關心當前的值是什么,只是想要把 a 賦值為 2。
再看例子二function foo(a) { console.log(a); // 2 } foo(2);
最后一行foo(..)函數的調用需要對 foo 進行 RHS 引用,意味著是取到 foo 的值,并且 (..)意味著 foo 需要被執行,因此它最好是一個函數類型的值
其中有一個容易被忽略的隱式賦值操作 a = 2,它發生在 2 被當做實參傳入 foo 中時。即實參 2 傳給了形參 a,需要一個 LHS 查詢
console 那一行還有對 a 的一次 RHS 引用(或者叫查詢),同時console.log(..)本身也需要一個 RHS 引用,即對 console 對象進行 RHS 查詢,并且檢查得到的值中是否有一個叫做 log 的方法。
書中有一段引擎和作用域的對話,有助于很好的理解例子二,see YDKJS github
小測驗function foo(a) { var b = a; return a + b; } var c = foo(2);
試試找出其中的3處 LHS 查詢,4處 RHS 查詢
答案:
LHS 查詢:
c = ..;
a = 2(隱式變量分配)
b = ..
RHS 查詢
foo(2..
= a;
a ..
.. b
小結參考原書中文版P12,英文版見 github
作用域是一套規則,用于確定在何處以及如何查找變量(標識符)。
如果查找的目的是對變量進行賦值,就會使用 LHS 查詢;如果目的是獲取變量的值,就會用 RHS 查詢。
賦值操作會導致 LHS 查詢。 = 操作符或調用函數時傳入參數的操作都會導致關聯作用域的賦值操作, 即都會導致 LHS 查詢。
JavaScript 引擎首先會在代碼執行前對其進行編譯,在這個過程中,像var a = 2 這樣的聲明會被分解成兩個獨立的步驟:
首先,var a在其作用域中聲明新變量。這會在最開始的階段,也就是代碼執行前進行。
接下來,a = 2會查詢(LHS查詢)變量 a 并對其進行賦值。
LHS 和 RHS 查詢都會在當前執行作用域中開始,如果有需要(也就是說它們沒有找到所需的標識符),就會向上級作用域繼續查找目標標識符,這樣每次上升一級作用域,最后到達全局作用域,無論找到或沒找到都將停止。
不成功的 RHS 引用會導致拋出 ReferenceError 異常。不成功的 LHS 引用會導致自動隱式地創建一個全局變量(非嚴格模式下),該變量使用 LHS 引用的目標作為標識符,或者拋出 ReferenceError 異常(嚴格模式下)。
參考我的blog 原文:JS-LHS-RHS
You Dont Know JS
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/87266.html
摘要:關于兩個專業術語的討論起自對你不知道的一書的閱讀學習。遇到,編譯器會詢問作用域是否已經有一個該名稱的變量存在于同一個作用域的集合中。摘錄來自你不知道的。 JS 編譯之 LHS RHS 一、前言 最近和朋友聊技術的時候,聊到 LHS RHS,我竟然沒聽說過 沒聽說過。。。 于是成功引起了我的好奇心。 關于兩個專業術語的討論起自對《你不知道的JavaScript》一書的閱讀學習。 二、編譯...
摘要:本文為你不知道的上卷中關于作用域相關的知識點的總結。第一層代表當前作用域,大樓的頂層代表全局作用域。如果一定要找一個點與動態詞法作用域扯上關系的話,那就是值了。 本文為《你不知道的JavaScript(上卷)》中關于作用域相關的知識點的總結。 作用域 賦值操作 變量的賦值操作實際上有兩個動作,首先編譯器會在當前作用域中聲明一個變量(如果之前沒有聲明過),然后在運行時引擎會在作用域中查找...
摘要:查詢是在作用域鏈中,一級級的往上查找該變量的引用。作用域和作用域鏈作用域的概念,應該兩張圖幾句話就能解釋吧。這個建筑代表程序中的嵌套作用域鏈。一層嵌一層的作用域形成了作用域鏈,變量在作用域鏈中的函數內得到了自己的定義。 javascript作用域和閉包之我見 看了《你不知道的JavaScript(上卷)》的第一部分——作用域和閉包,感受頗深,遂寫一篇讀書筆記加深印象。路過的大牛歡迎指點...
摘要:一旦到達頂層全局作用域,可能找到,也可能沒有找到,查找過程都必須停止。當引擎執行查詢時,如果查詢在所有嵌套的作用域中遍尋不到所需的變量,引擎就會拋出異常。代表作用域判別失敗相關,而則代表作用域判別成功了,但是對結果的操作是非法或不合理的。 什么是作用域 對于幾乎所有編程語言,最基本的功能之一就是能夠存儲變量的值,并且能在之后對這個值進行訪問和修改。這樣就會帶來幾個問題,這些變量存儲在哪...
摘要:作用域鏈前面說,作用域是根據名稱查找變量的一套規則。把這樣一層一層嵌套的作用域,叫做作用域鏈。因為這個函數名無法被外部作用域所訪問。的進階用法是給其傳入參數這樣的好處是可以縮短查詢時的作用域鏈。 上一篇文章中分析了 JS 中的數據類型和變量。這一篇文章將分析作用域,以及回答上一篇文章中變量提升的原因。 什么是作用域 作用域是一套規則,保存著變量,等待被引擎所查找。 var a = 1;...
閱讀 2197·2021-11-25 09:43
閱讀 1165·2021-11-23 09:51
閱讀 3499·2021-11-23 09:51
閱讀 3628·2021-11-22 09:34
閱讀 1543·2021-10-09 09:43
閱讀 2119·2019-08-30 15:53
閱讀 3161·2019-08-30 14:07
閱讀 568·2019-08-28 18:14