iT邦幫忙

2021 iThome 鐵人賽

DAY 9
0
自我挑戰組

JavaScript 奇奇怪怪的核心觀念系列 第 9

(Day9) 運算子中的優先性及相依性

  • 分享至 

  • twitterImage
  •  

運算子優先性 (Precedence)

先來看一個範例

4 / 2 * 2 + 2 //6

這段程式碼執行下來答案是 6 ,很符合我們對數學先乘除後加減的概念。

但在 JavaScript 中還有其他運算子,扣掉我們較熟悉的算數使用的算數運算子,如何知道其他運算子的使用順序呢?

MDN 文件中就有提供相關的表格。

在文件中我們可以看到 + 號算數運算子優先性是 13 ,*/ 除,是 14 ,因此也會是我們熟知的先乘除後加減,但 JS 是怎麼判斷範例中先 /* 呢?

運算子相依性 (Associativity)

這時就要介紹運算子另一個特性,『相依性』,而相依性的特性就是,如果運算子是相同優先性,那麼 JavaScript 會根據設定,從指定方向開始執行,從文件上也可以看到 */ 的算數運算子是 『從左至右』。

再來看看一個滿常見的前端面試問題:

1 < 2 < 3 // true

答案是 true 跟我理解一般理解的一樣,那麼稍微調整一下順序:

3 > 2 > 1 //false

這時就變成 false 了,這是因為相依性的特性,會讓上面範例在執行整段程式碼是分開的,會先執行 3 > 2 接者才會執行 2 > 1
但上面的說法其實不太正確, 3 > 2 這段是表達式,而表達式的特性就是會回傳值。
3 > 2 這段表達式回傳的會是 true ,因此實際上會是 true > 1 ,而不是我們原先認為的 2 > 1
所以上面這一段在 JavaScript 中是這樣的:

3 > 2 
true > 1

( true 會隱含轉型變成 1 , 1 > 1 因此最後回傳 false )

再來根據表達式特性再提一個賦值狀況:

var a = 1;
var b = 2;
a = b = 3;

結果我們查詢 a 、 b 值都會是 3
在我們看來會是他的執行順序會是:

var a = 1;
var b = 2;

b = 3;
a = b

但要注意這個執行順序並不正確,這邊實際上的情況是:

b = 1 時,因為這段是表達式,所以會回傳 1 ,接者才是 a 被賦予回傳的 1
所以 a 被賦予的實際上是 b = 1 回傳的值。

我們可以使用 Object.defineProperty() 鎖定物件屬性中的值 來驗證這個觀念:

var obj = {};

Object.defineProperty(obj, 'test', {
  value: 0,
  writable: false,
})

這個寫法會綁定物件 objtest 屬性的值,接者新增一個變數來替換 obj 中的 test:

var obj = {};

Object.defineProperty(obj, 'test', {
  value: 0,
  writable: false,
})

var num = 1
obj.test = num
obj.test //0

確認 obj.test 是無法被更改的,接著使用連續賦值的動作看看結果如何:

var obj = {};

Object.defineProperty(obj, 'test', {
  value: 0,
  writable: false,
})

var num = 1
num = obj.test = 5566
console.log(num,obj.test) // ???

結果回傳的是 55660,這是因為 5566 雖然沒有成功賦予到 obj.test 上,但是 obj.test = 5566 這段表達式會回傳 5566,因此 num 最後是獲得這個回傳的 5566

參考資料


上一篇
(Day8) 隱含轉型 - 轉成 Boolean & 寬鬆相等 vs 嚴格相等
下一篇
(Day10) 物件基礎介紹
系列文
JavaScript 奇奇怪怪的核心觀念30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言