標籤:

一道面試題所引發的運算符的優先順序的思考

剛才無意間看到了一道面試題

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:前端入门 |