一般來說,我們常看到的運算子就是所謂的 + - * / 跟 %
1 | let x = 5; |
優先順序則是跟我們在算數學的時候一樣,有括號者優先
1 | let x = 10; |
比較運算子則有3種
- 嚴格相等
- 抽象 ( 寬鬆 ) 相等
- 與關係當成不同型態
現在我們可以來看一下 嚴格 跟 寬鬆 的差別
== 跟 === (相等運算子)
我們都知道 ==
是一般的相等運算子,一般相等運算子 不限
兩邊差異,在處理兩邊數值不同型別的情況時都會對他們進行 強制轉型
1 | console.log(false == ""); |
嚴格的相等運算子
1 | console.log(false === ""); |
這個運算子會先比較兩邊的型別
,然後再看數值,因此也被稱為全等於
物件的部分
1 | console.log({} === []); |
emm…看起來答案都是 false 呢……
這是因為在JS裡,字串、數值、bool、undefined、null 這幾個型別都只能被概括的被稱為 純值 ,所以說 1 這個數字永遠都是 1 ,不應該有 1 === “1” 的想法。
當物件被創造後、賦值給變數時,變數所儲存的內容不是整個物件內容,而是該物件存放的記憶體位置。
也就是說整個物件在創造後會分配到另一特定記憶體空間,然後變數拿到的只是記憶體位置,而不是整個物件的數值內容…….
所以在比較的時候不是比較物件內容,而是比較物件存放的記憶體位置……
1 | let a = {}; |
上面的這個例子就很明顯了,當某物件創建完後,該物件的記憶體位置會存放在 變數a 內,而後我們再將變數 a的內容指派給變數 b,所以 a 跟 b 的內容都是同一記憶體位置……
! = 跟 ! = =
結果完全相反,不過 ! = 跟 == 一樣,會自動觸發轉型
1 | console.log([] !== []) |
大魚小魚等於
基本上我們都會使用這些運算子,那在這裡我們先補充一下 若兩邊型態不同
時的做法
- 如果兩邊都不是純值,則盡量轉為數值型別
- 如果都是字串,則按照 Unicode 比較
- 如果一邊是數值、一邊是字串,則將字串轉為數值比較
- 布林值、
null
、defined
會被轉值為數值型別,布林值的false轉型 → 0 ,true → 1,null → 0 unfined
轉型後會得到 NaN 的結果,而根據文件規範,NaN
與任何數值比較都會得到 false 的結果
1 | console.log(5 > undefined) |
邏輯運算子
and 運算子 ( && )
1 | console.log(1 && 0) |
and 運算子很簡單,兩邊相同時為 true 其它為 false
or 運算子 ( || )
1 | console.log(1 || 0) |
當有一邊為 true 時就為 true,如果兩邊皆為 false 則為 false
not 運算子 ( ! )
1 | console.log(!true) |
這個運算子是一元運算子,代表反向的邏輯。
位元運算子
運算子 | 說明 | 範例 |
---|---|---|
^ | xor | 1 ^ 1 → 0 |
~ | not | 1100 → 0011 |
<< | 左移 | ob1010 << 1 → 0b10100 |
>> | 有極右移 | 512 >> 3 → 64 |
>>> | 補零右極 | ~(512) >>> 3 → 2147483391 |
強制轉型
明確 ? 不明確 ?
好問題。一般來說我們在比較值的時候有2種作法
- 使用轉型 String( ) 、Number( )
- 如果自己沒有主動轉,JS會很貼心的幫你轉
上面的方法前者稱為 明確的轉型
,後者稱為 隱含的轉型
如果我們使用 Number("2")
,這個動作就被稱為 明確的
轉型,不過因為 JS 是弱型別
的語言( 弱型別的語言對數值運算型別的差異容忍度較高 ),所以數值型態能互相轉換,所以就有了 隱含
的轉型現象。
一般來說強制轉型分為三類。
我們先來看看第一類。
字串
明確轉型
1 | String("2"); |
隱含強制轉型
1 | String(123); // 明確 |
其他類型
1 | String(111) |
布林值
明確強制轉型
1 | Boolean() |
隱含強制轉型
透過邏輯運算子以及 if 判斷式內的條件區塊來觸發
1 | Boolean(3); // 明確轉型 |
反正不果怎麼轉都只有 true 跟 false 兩種結果
但是有些特定值不管怎麼轉都會只有 false or true 單一種結果,這些值會被稱作 Falsy Value / Trusy Value
Falsy Value
- 0
- NaN
- ‘ ’ ( 空字串 )
- False
- null
- undefined
Trusy Value
'false'
( 空字串以外的字串 )- ( 空陣列 )
- { } ( 空物件 )
- function( ){ } ( 空函式 )
數值
明確轉型
1 | Number(123) // 123 |
隱含強制轉型
透過運算子觸發
→ 有4種
- 大、小運算子
- 算數運算子 ( 注意
+
) - 在任一其他類型的數值面前使用加法運算子
+
來觸發轉型 - 寬鬆的數值比較 (
==
、!=
)
物件轉布林
→ 任何非純值類零的數值,都會被轉型為 true
物件轉字串與數值
1 | let a = {} |
JS 根據 ECMAScript 的規範,使用一個叫做 ToPrimitive 的演算流程,這個流程分別使用 toString
與 ValueOf
兩個方法搭配整個物件當作輸入值來判斷結果。而這兩個方法在所有的物件類型的數值上都可以呼叫,也可以透過複寫來自定。
通常物件都會有預設的 toString()
方法。如股宣告一個變數,直接呼叫其上面的 toString()
方法,就會得到 [object Object]
的字串結果,這是物件被轉為字串型別的預設值。
至於 ValueOf
方法,也是物件上的一個預設方法,這個方法同樣影響物件轉型的結果
1 | let a = { test : 'mid' } |
恩…預設會回傳整個物件本身。