首頁 > 軟體

JavaScript中的LHS和RHS分析詳情

2022-04-06 19:02:16

前言:

對於LHS和RHS,從字面意思來說是​​ Left Hand Side​​和​​ Right Hand Side​​即左手邊和右手邊,一般可以理解為賦值操作的左側和右側,然而不能片面的用​​=​​號左邊還說右邊去判斷是​​LHS​​還是​​RHS​​通俗的理解,​

​LHS​​是賦值操作即可以看做是在往記憶體中儲存值,而​​RHS​​是取值操作,它是從記憶體中進行檢索。事實上賦值操作還有其他幾種形式,因此在概念上最好將其理解為“賦值操作的目標是誰(LHS)”以及“誰是賦值操作的源頭(RHS)”。

進一步理解

這兩種不同的參照方式對沒有宣告的變數的處理方式上是不同的,而這個不同之處對於我們編寫程式碼和分析JS引擎報錯是很有益處的。 當對一個變數執行​​RHS​​查詢時,如果遍歷該變數所在處的詞法作用域未能找到這個變數,JS引擎就會丟擲​​ ReferenceError​​錯誤如果成功查詢到了這個變數,但是對這個變數執行不合理操作,比如對一個非陣列的變數執行下標取值,JS引擎就會丟擲​​ TypeError​​錯誤,甚至跟你說這個操作對應的只能是陣列。當對一個變數執行​

​LHS​​查詢時,同樣在遍歷作用域後無法找到該變數,在非​​ES5​​的嚴格模式下,系統就會自動在全域性作用域中建立一個同名變數,並將參照轉移到該新建的全域性變數中。而在​​ES5​​的嚴格模式下,LHS查詢失敗時JS引擎會丟擲一個同RHS一樣的​​ ReferenceError ​​錯誤。![​

因此,對LHS查詢和RHS查詢的仔細區分和理解無論是對JS執行過程本身的理解還是分析錯誤都是有所好處的。

在JS語言特點

JavaScript在型別上通常會被歸類為“動態”或“解釋執行”語言,但事實上它是一門編譯語言。

JavaScript是世界上最流行的指令碼語言,因為你在電腦、手機、平板上瀏覽的所有的網頁,以及無數基於HTML5的手機App,互動邏輯都是由JavaScript驅動的。

簡單地說,JavaScript是一種執行在瀏覽器中的解釋型的程式語言。

不過這種語言與傳統的編譯語言還是有點不同,它不是提前編譯的,編譯結果也不能在分散式系統上進行移植,做過前端專案部署的同學,也會發現,我們將專案編譯完成之後是個​​dist​​檔案,之後將這整個檔案直接放在web伺服器上面,如nginx、tomcat等,這個是個很純粹的單機部署。

編譯特點

比如說,執行一個賦值語句,我們的JavaScript引擎要做多少事呢?

var girlfriend = 'naug'

事實上做了兩步,JavaScript 會將其看成兩句宣告:​​var girlfriend;​​和​​girlfriend = 'naug';​

  • 定義宣告在編譯階段進行
  • 賦值宣告會被留在原地等待執行階段。

分析

變數的賦值操作會執行兩個動作,首先編譯器會在當前作用域中宣告一個變數(如果之前沒有宣告過),然後在執行時引擎會在作用域中查詢該變數,如果能夠找到就會對它賦值。 而要講的LHS 和 RHS就是上面說的對變數的兩種查詢操作,查詢的過程是由作用域(詞法作用域)進行協助,在編譯的第二步中執行。 前面我們說到,​​LHS​​是賦值操作就是在往記憶體中儲存值,而​​RHS​​是取值操作可以從記憶體中檢索值,那麼基於這個資訊點,我們再來分析一個複雜一些的例子

function together(people) {
var girlFriend = people;
return girlFriend
}


var luckyGirl = together('naug');

問,這個例子中一共用了多少個LHS和RHS? 答,3個LHS和3個RHS

  • LHS

- 函數裡面隱藏的​​people = 'naug'​​(隱式變數分配),當呼叫​​together('naug')​​時,需要將實參​​naug​​賦值給形參​​people​​,所以對​​people​​需要進行​​LHS​​操作 - 對於​

​girlFriend = people​​ ,中,girlFriend在賦值操作的左邊,即將該變數往該作用域空間所在記憶體區間儲值,也就是進行LHS操作 - ​

​luckyGirl = ... ​​,中​​luckyGirl​​在賦值操作的左邊,需要為該變數在記憶體中進行儲值,即對​​luckyGirl​​進行​​LHS​​操作

  • RHS

- ​​girlFriend = people​​ ,中​​people​​在賦值操作的右邊,​​javascript​​引擎需要對其進行取值操作,因此進行​​RHS​​查詢 - ​

​return girlFriend​​,由於需要知道​​girlfriend​​的值,因此進行​​RHS​​查詢到​​girlfriend​​的值 - ​

​luckyGirl = together('naug')​​,中​​together('naug')​​在賦值操作的右邊因此需要知道該函數執行之後的值 小結:如果查詢的目的是對變數進行賦值,那麼就會使用LHS查詢;如果目的是獲取變數的值,就會使用RHS查詢。

區分 LHS 和 RHS 的重要性

因為在變數還沒有宣告(在任何作用域中都無法找到該變數)情況下,這兩種查詢行為是不一樣的。 對於作用域的分析可以看一下這篇文章​ ​關於JS中的作用域​​,這裡想說的是LHS和RHS都會在當前執行作用域中開始,如果有需要(也就是說他們沒有找到所需的識別符號),就會向上級作用域繼續查詢目標識別符號,依次上升一次作用域,最後抵達全域性作用域,最後無論找到或沒找到都將到此為止

總結:

不成功的RHS參照會導致丟擲​​ReferenceError​​異常。不成功的LHS參照會導致自動隱式地建立一個全域性變數(非嚴格模式下),該變數使用LHS參照的目標作為識別符號,或者丟擲​​ReferenceError​​異常(嚴格模式下)。

到此這篇關於JavaScript中的LHS和RHS分析詳情的文章就介紹到這了,更多相關JavaScript中的LHS和RHS內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!


IT145.com E-mail:sddin#qq.com