快速理解 JavaScript 中的 LHS 和 RHS 查詢(xún)的用法
JavaScript 程序中的一段源代碼在執(zhí)行之前會(huì)經(jīng)歷三個(gè)步驟,統(tǒng)稱(chēng)為 編譯
- 分詞/詞法分析
- 解析/語(yǔ)法分析
- 代碼生成
先看原書(shū)對(duì)一個(gè)賦值操作的拆解說(shuō)明:
變量的賦值操作會(huì)執(zhí)行兩個(gè)動(dòng)作,首先編譯器會(huì)在當(dāng)前作用域中聲明一個(gè)變量(如果之前沒(méi)有聲明過(guò)),然后在運(yùn)行時(shí)引擎會(huì)在作用域中查找該變量,如果能夠找到就會(huì)對(duì)它賦值。 --- 《你不知道的JavaScript(上卷)》 P7
而要講的 LHS 和 RHS 就是上面說(shuō)的對(duì)變量的兩種查找操作,查找的過(guò)程是由作用域(詞法作用域)進(jìn)行協(xié)助,在編譯的第二步中執(zhí)行。
LHS 和 RHS
- 字面意思其實(shí)是
Left Hand Side和Right Hand Side即左手邊和右手邊 - 一般可以理解為
賦值操作的左側(cè)和右側(cè)
先看個(gè)例子一
console.log(a);
這里對(duì) a 是一個(gè) RHS 引用,因?yàn)?a 并沒(méi)有賦予任何值,目的是為了取到 a 的值并打印出來(lái)。
a = 2;
這里對(duì) a 是一個(gè) LHS 引用,因?yàn)閷?shí)際上我們不關(guān)心當(dāng)前的值是什么,只是想要把 a 賦值為 2。
再看例子二
function foo(a) {
console.log(a); // 2
}
foo(2);
- 最后一行foo(..)函數(shù)的調(diào)用需要對(duì) foo 進(jìn)行 RHS 引用,意味著是取到 foo 的值,并且 (..)意味著 foo 需要被執(zhí)行,因此它最好是一個(gè)函數(shù)類(lèi)型的值
- 其中有一個(gè)容易被忽略的隱式賦值操作 a = 2,它發(fā)生在 2 被當(dāng)做實(shí)參傳入 foo 中時(shí)。即實(shí)參 2 傳給了形參 a,需要一個(gè) LHS 查詢(xún)
- console 那一行還有對(duì) a 的一次 RHS 引用(或者叫查詢(xún)),同時(shí)console.log(..)本身也需要一個(gè) RHS 引用,即對(duì) console 對(duì)象進(jìn)行 RHS 查詢(xún),并且檢查得到的值中是否有一個(gè)叫做 log 的方法。
- 書(shū)中有一段引擎和作用域的對(duì)話(huà),有助于很好的理解例子二,see YDKJS github
小測(cè)驗(yàn)
function foo(a) {
var b = a;
return a + b;
}
var c = foo(2);
試試找出其中的3處 LHS 查詢(xún),4處 RHS 查詢(xún)
答案:
LHS 查詢(xún):
c = ..;
a = 2(隱式變量分配)
b = ..
RHS 查詢(xún)
foo(2..
= a;
a ..
.. b
小結(jié)
參考原書(shū)中文版P12,英文版見(jiàn) github
- 作用域是一套規(guī)則,用于確定在何處以及如何查找變量(標(biāo)識(shí)符)。
- 如果查找的目的是對(duì)變量進(jìn)行賦值,就會(huì)使用 LHS 查詢(xún);如果目的是獲取變量的值,就會(huì)用 RHS 查詢(xún)。
- 賦值操作會(huì)導(dǎo)致 LHS 查詢(xún)。 = 操作符或調(diào)用函數(shù)時(shí)傳入?yún)?shù)的操作都會(huì)導(dǎo)致關(guān)聯(lián)作用域的賦值操作, 即都會(huì)導(dǎo)致 LHS 查詢(xún)。
- JavaScript 引擎首先會(huì)在代碼執(zhí)行前對(duì)其進(jìn)行編譯,在這個(gè)過(guò)程中,像var a = 2 這樣的聲明會(huì)被分解成兩個(gè)獨(dú)立的步驟:
- 首先,var a在其作用域中聲明新變量。這會(huì)在最開(kāi)始的階段,也就是代碼執(zhí)行前進(jìn)行。
- 接下來(lái),a = 2會(huì)查詢(xún)(LHS查詢(xún))變量 a 并對(duì)其進(jìn)行賦值。
- LHS 和 RHS 查詢(xún)都會(huì)在當(dāng)前執(zhí)行作用域中開(kāi)始,如果有需要(也就是說(shuō)它們沒(méi)有找到所需的標(biāo)識(shí)符),就會(huì)向上級(jí)作用域繼續(xù)查找目標(biāo)標(biāo)識(shí)符,這樣每次上升一級(jí)作用域,最后到達(dá)全局作用域,無(wú)論找到或沒(méi)找到都將停止。
- 不成功的 RHS 引用會(huì)導(dǎo)致拋出 ReferenceError 異常。不成功的 LHS 引用會(huì)導(dǎo)致自動(dòng)隱式地創(chuàng)建一個(gè)全局變量(非嚴(yán)格模式下),該變量使用 LHS 引用的目標(biāo)作為標(biāo)識(shí)符,或者拋出 ReferenceError 異常(嚴(yán)格模式下)。
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
JS target與currentTarget區(qū)別說(shuō)明
target在事件流的目標(biāo)階段;currentTarget在事件流的捕獲,目標(biāo)及冒泡階段。只有當(dāng)事件流處在目標(biāo)階段的時(shí)候,兩個(gè)的指向才是一樣的,而當(dāng)處于捕獲和冒泡階段的時(shí)候,target指向被單擊的對(duì)象而currentTarget指向當(dāng)前事件活動(dòng)的對(duì)象(一般為父級(jí))。2011-08-08
Javascript仿PHP $_GET獲取URL中的參數(shù)
這篇文章主要介紹了Javascript仿PHP $_GET獲取URL中的參數(shù)代碼實(shí)例,需要的朋友可以參考下2014-05-05
JavaScript 中獲取數(shù)組最后一個(gè)元素方法匯總
在JavaScript中,獲取數(shù)組最后一個(gè)元素的方法有很多種。今天我們就來(lái)匯總一下JavaScript獲取數(shù)組最后一個(gè)元素的幾種方法,需要的朋友可以參考下2023-02-02
egg.js的基本使用和調(diào)用數(shù)據(jù)庫(kù)的方法示例
這篇文章主要介紹了egg.js的基本使用和調(diào)用數(shù)據(jù)庫(kù)的方法示例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-05-05
JavaScript中的JSON轉(zhuǎn)為Python可讀取
本文主要介紹了JavaScript中的JSON轉(zhuǎn)為Python可讀取,文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-01-01
微信小程序?qū)崿F(xiàn)樹(shù)莓派(raspberry pi)小車(chē)控制
這篇文章主要為大家詳細(xì)介紹了微信小程序?qū)崿F(xiàn)樹(shù)莓派(raspberry pi)小車(chē)控制,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-02-02
JS實(shí)現(xiàn)點(diǎn)擊按鈕自動(dòng)增加一個(gè)單元格的方法
這篇文章主要介紹了JS實(shí)現(xiàn)點(diǎn)擊按鈕自動(dòng)增加一個(gè)單元格的方法,實(shí)例分析了javascript操作表格單元格的技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-03-03
js對(duì)url進(jìn)行編碼解碼的三種方式總結(jié)
為一個(gè)字符串進(jìn)行URL編碼很容易,只需要調(diào)用encodeURI,傳入要編碼的字符串即可,而且實(shí)現(xiàn)的方法不止這一個(gè),下面這篇文章主要給大家介紹了關(guān)于js對(duì)url進(jìn)行編碼解碼的三種方式,需要的朋友可以參考下2023-02-02

