之前看過 《You don't know js》中說到的 LHS ,RHS.
然而還是對這個知識點懵懵懂懂 嫡霞, 了解粗淺较木。
碰到這種題目一時間還是無法理解:
var foo = { n: 1 };
var bar = foo;
foo.x = foo = { n: 2 };
console.log(foo.x) // ?
console.log(bar.x) // ?
在這之前先簡單說一下前提概念:
簡述編譯原理
JavaScript 程序中的一段源代碼在執(zhí)行之前會經(jīng)歷三個步驟,統(tǒng)稱為 編譯
1. 分詞/詞法分析
2. 解析/語法分析
3. 代碼生成
先看原書對一個賦值操作的拆解說明:
變量的賦值操作會執(zhí)行兩個動作卑吭,
首先編譯器會在當(dāng)前作用域中聲明一個變量(如果之前沒有聲明過)泞歉,
然后在運行時引擎會在作用域中查找該變量,如果能夠找到就會對它賦值谚攒。
而要講的 LHS 和 RHS 就是上面說的對變量的兩種查找操作,查找的過程是由作用域(詞法作用域)進行協(xié)助氛堕,在編譯的第二步中執(zhí)行馏臭。
LHS 和 RHS
字面意思其實是 Left Hand Side和 Right Hand Side 即左手邊和右手邊
一般可以理解為 賦值操作的左側(cè)和右側(cè)
但更準確來說,
LHS 是 查找變量的 內(nèi)存地址 (類似于C語言中的變量對應(yīng)的指針值)
RHS 是 查詢變量的 值.
先舉個最簡單的例子:
var a=1;
從這里 發(fā)生了一次 LHS 引用: var a...
,獲取 a 的變量地址讼稚,然后把 1 賦值給 a.
再來一個:
console.log(a);
顯然 , 為了打印 變量 a 的值 , 這里需要獲取到 a的具體值 , 發(fā)生了 RHS
延伸到函數(shù):
function sayHi(name){
console.log(name);
}
sayHi('小明');
第一步括儒,這里 sayHi ('小明')
,其中 sayHi...
調(diào)用了RHS,獲取這個函數(shù)的內(nèi)容.
第二步绕沈,括號里面進行了一次傳參,也就是 name = 小明
, 發(fā)生了一次LHS帮寻,把 小明
賦值給 name
第三步乍狐, console.log(..)
本身也需要一個 RHS 引用,即對 console 對象進行 RHS 查詢规婆,并且檢查得到的值中是否有一個叫做 log 的方法澜躺。
第四步蝉稳, console.log(name)
, 為了獲取到 name
具體的值 發(fā)生RHS ,
總結(jié)就是 , 執(zhí)行 sayHi('小明')
這個過程中 ,一共發(fā)生了 一次LHS抒蚜,三次RHS。
可以來道小題練練手:
試試找出其中的3處 LHS 查詢耘戚,4處 RHS 查詢
function foo(a) {
var b = a;
return a + b;
}
var c = foo(2);
答案:
LHS 查詢
c = ..;
a = 2(隱式變量分配)
b = ..
RHS 查詢
foo(2..
= a;
a ..
.. b
重新做題
接下來回到文中開頭的題目:
var foo = { n: 1 };
var bar = foo;
foo.x = foo = { n: 2 };
console.log(foo.x) // ?
console.log(bar.x) // ?
詳細解析可以參考
https://juejin.im/entry/5acb0dc55188255c5668bbe2?utm_source=gold_browser_extension