一道面試題所引發的運算符的優先順序的思考
var a = {n: 1}nvar b = a;na.x = a = {n: 2}nnconsole.log(a.x);nconsole.log(b.x)n
這道題考察了兩個知識點
- 內存空間
- 運算符的優先順序
關於內存空間我掌握的還可以,具體可以看 前端基礎進階(一):內存空間詳細圖解
而對於運算符的優先順序,是我忽略了,之前梳理知識點的時候是按照 讀書筆記《JavaScript高級程序設計》(第3版) 這本書來來梳理的,這本書好像也遺漏了這個知識點(或者是我粗心了)
總之不管怎樣,今天也得好好整理這一部分的知識
優先順序
運算符的優先順序決定了表達式中運算執行的先後順序,優先順序高的運算符最先被執行。
下面是一個簡單的例子:
3 + 4 * 5 // 計算結果為23n
很簡單的式子,這說明乘法運算符(*)比起加法運算符(+)有著更高的優先順序,所以它會被最先執行。
毫無疑問這沒什麼難度
那如果是優先順序一樣的運算符呢
結合性
結合性決定了擁有相同優先順序的運算符的執行順序。考慮下面這個表達式:
a 運算符 b 運算符 cn
左結合(從左到右計算)相當於把左邊的子表達式加上小括弧
(a 運算符 b) 運算符 cn
類似的,右關聯(從右到左計算)相當於
a 運算符 (b 運算符 c)n
賦值運算符是右結合的,所以你可以這麼寫:
a = b = 5;n
結果 a 和 b 的值都會成為5。這是因為賦值運算符的返回結果就是賦值運算符右邊的那個值,具體過程是 =>
b 被賦值為5,然後 a 也被賦值為 b=5 的返回值,也就是5。
原來是這樣啊
有沒有一個匯總表呢
匯總表
發個鏈接吧,可到此處去查閱
運算符優先順序首尾呼應
最後再來說說開篇提到的面試題
var a = {n: 1}nvar b = a;na.x = a = {n: 2}nnconsole.log(a.x);nconsole.log(b.x)n
- 變數 a 指向對象 {n: 1}
- 變數 b 也指向到對象 {n: 1},他倆現在指向同一個對象
- 到重點了, a.x 中的 . 的優先順序高於 =
- 所以第一步執行 a.x,現在的變數 a 指向的對象添加了一個 x 屬性,變成了 {n: 1, x: undefined},b 當然不變依然指向這個對象
- 接下來繼續分析 a.x = a = {n: 2}
- 考慮到賦值號的結合性是右結合,所以以上式子等價於 a.x = (a = {n: 2})
- 那就是先進行 a = {n: 2} 咯,這語句的意思就是,堆內存內重新開闢了一塊空間存放對象 {n: 2},a 就指向了這塊新的內存空間,b 指向的還是原來的沒變
- 右側的賦值號運算符執行完繼續執行左側的賦值號運算符 a.x = a = {n: 2},由於 a = {n: 2} 返回 a 本身,所以 a.x 的屬性值被賦值為 a
- 是不是有點懵,為了更好的說明情況,我把這裡面的 a 區分一下,並且重新說一下上一句話
- 右側的賦值號運算符執行完繼續執行左側的賦值號運算符 a(舊).x = a(新) = {n: 2},由於 a(新) = {n: 2} 返回 a(新) 本身,所以 a(舊).x 的屬性值被賦值為 a(新)
對照上圖再看看這道面試題
var a = {n: 1}nvar b = a;na.x = a = {n: 2}nnconsole.log(a.x); // undefinednconsole.log(b.x) // {n: 2}n
(完)
推薦閱讀:
※「每日一題」JSONP 是什麼?
※慢時光
※引入 CSS 的方式
※前端開發者應知必會:瀏覽器是如何渲染網頁的
※「每日一題」CSRF 是什麼?
TAG:前端入门 |