JS編譯之 LHS RHS(你不知道的JavaScript 小記一)

JS 編譯之 LHS RHS

1、前言

最近和朋友聊技術的時候,聊到 LHS RHS,我居然沒據說過 沒據說過。。。 因而成功引發了個人好奇心。 關於兩個專業術語的討論起自對《你不知道的JavaScript》一書的閱讀學習。編程

2、編譯簡述

儘管一般將JavaScript歸類爲「動態」或「解釋執行」語言,但事實上它是一門編譯語言。這個事實對你來講可能顯而易見,也可能你聞所未聞,取決於你接觸過多少編程語言,具備多少經驗。但與傳統的編譯語言不一樣,它不是提早編譯的,編譯結果也不能在分佈式系統中進行移植。編程語言

儘管如此,JavaScript引擎進行編譯的步驟和傳統的編譯語言很是類似,在某些環節可能比預想的要複雜。分佈式

在傳統編譯語言的流程中,程序中的一段源代碼在執行以前會經歷三個步驟,統稱爲「編譯」。函數

  • 分詞/詞法分析(Tokenizing/Lexing)
  • 解析/語法分析(Parsing)
  • 代碼生成

比起那些編譯過程只有三個步驟的語言的編譯器,JavaScript引擎要複雜得多。例如,在語法分析和代碼生成階段有特定的步驟來對運行性能進行優化,包括對冗餘元素進行優化等。性能

JavaScript引擎,編譯器概述學習

  • 從頭至尾負責整個JavaScript程序的編譯及執行過程。
  • 引擎的好朋友之一,負責語法分析及代碼生成等髒活累活。

摘錄來自: 「你不知道的JavaScript(上卷)」優化

以上內容看起來有些高深,可是與下面內容並沒有多少關聯,只是背景,有興趣的能夠深刻研究一下。
對於下面的內容,咱們只須要知道 JS代碼的執行須要JS引擎的,而JS引擎的在執行代碼前會先對其進行編譯(有些地方稱之爲預解析),引擎最終執行的是通過編譯以後的代碼
LHS RHS 這兩個術語就是出如今引擎對變量進行查詢的時候,接下來看看在具體例子中 站在編譯器和引擎的角度看看它們是怎麼思考工做的,以及這個過程當中如何觸發了LHS RHS.code

3、具體代碼的編譯執行過程當中 如何觸發 LHS RHS

以書中的賦值語句爲示例ip

var a = 2;

事實上編譯器會進行以下處理。作用域

  1. 遇到var a,編譯器會詢問做用域是否已經有一個該名稱的變量存在於同一個做用域的集合中。若是是,編譯器會忽略該聲明,繼續進行編譯;不然它會要求做用域在當前做用域的集合中聲明一個新的變量,並命名爲a。
  2. 接下來編譯器會爲引擎生成運行時所需的代碼,這些代碼被用來處理a = 2這個賦值操做。引擎運行時會首先詢問做用域,在當前的做用域集合中是否存在一個叫做a的變量。若是是,引擎就會使用這個變量;若是不是,引擎會繼續查找該變量。

摘錄來自: 你不知道的JavaScript。

以上爲書中描述,可是我的以爲能夠補充一些描述以下

  1. 編譯器在編譯一段js代碼時,至關於對這段代碼進行預解析,爲了引擎更好的進行二次解析。在預解析時,先構建好代碼的上下文環境,創建做用域鏈,在每一個做用域中進行變量聲明提高和更特別的函數聲明提高。變量的聲明提高會在當前做用域的集合中聲明一個新的變量,如a。另外,在聲明每個新的變量以前,編譯器會詢問做用域是否已經有一個該名稱的變量存在於同一個做用域的集合中, 若有則報錯。

    console.log(a)
       var a = 2;

    的預解析以後,其實至關於

    var a
    console.log(a) // undefined
    a = 2;
  2. 接下來編譯器會爲引擎生成運行時所需的代碼,這些代碼被用來處理a = 2這個賦值操做。引擎運行時會首先詢問做用域,在當前的做用域集合中是否存在一個叫做a的變量。若是是,引擎就會使用這個變量;若是不是,引擎會沿做用域鏈繼續查找該變量;若是查到根做用域也沒有查到,會自動聲明a。

ps: 關於聲明提高,做用域鏈,若有疑惑,後續章節解釋。

上述過程當中,第二步中編譯器生成了代碼,引擎執行它時(第3行 a = 2),會經過查找變量a來判斷它是否已聲明過。查找的過程由做用域進行協助,可是引擎執行怎樣的查找,會影響最終的查找結果。
此時引擎會就在對變量a進行LHS查詢,另一個查詢的類型叫RHS。

4、LHS RHS 概念定義

我打賭你必定能猜到「L」和「R」的含義,它們分別表明左側和右側。
什麼東西的左側和右側?是一個賦值操做的左側和右側。

換句話說,當變量出如今賦值操做的左側時進行LHS查詢,出如今右側時進行RHS查詢。

講得更準確一點,RHS查詢與簡單地查找某個變量的值別無二致,而LHS查詢則是試圖找到變量的容器自己,從而能夠對其賦值。從這個角度說,RHS並非真正意義上的「賦值操做的右側」,更準確地說是「非左側」。

你能夠將RHS理解成retrieve his source value(取到它的源值),這意味着「獲得某某的值」。

LHS和RHS的含義是「賦值操做的左側或右側」並不必定意味着就是「=賦值操做符的左側或右側」。賦值操做還有其餘幾種形式,所以在概念上最好將其理解爲「賦值操做的目標是誰(LHS)」以及「誰是賦值操做的源頭(RHS)」。

摘錄來自: 你不知道的JavaScript。

以上爲書中解釋,以賦值操做符爲標誌,加上一些特殊狀況的理解。可是我以爲能夠有其餘的理解方式。

5、LHS RHS 我的理解

講得更準確一點,RHS查詢與簡單地查找某個變量的值別無二致,而LHS查詢則是試圖找到變量的容器自己,從而能夠對其賦值。

舉個例子來理解就是:RHS是找到你在哪一個座位,看看你的樣子拍個照;LHS一樣是找到你在哪一個座位,可是一眼不看直接踹飛 換我的坐這兒。
簡單來說有兩個區別:1.關不關心你如今的狀態 2.是否改變你的狀態(不論是改變一部分,仍是徹底改變)。

因此書中這句原話

是引擎執行怎樣的查找,會影響最終的查找結果。

我以爲能夠反過來理解,正是由於查找結果的不一樣分出了兩種查找類型。

左側右側的分類理解更可能是以 代碼的形態爲標準分類的。我的以爲能夠按查找目的爲標準分類,RHS是爲了讀取變量的值,LHS是爲了改變變量的值。

6、總結

LHS RHS就是對變量查詢的兩種查詢類型,區別在於查詢的結果,或者說查詢的目的,在代碼上直觀體現爲變量位置形態的不一樣。其中涉及的編譯器引擎工做過程,對於更深刻的理解掌握js頗有幫助。 其中我的理解有不合適的地方還請指正。

相關文章
相關標籤/搜索