[JavaScriptWeird]No.17 比較運算子

前言

來談談 JavaScript 的比較運算子,之前我們紀錄的所有東西,單獨來看可能不知道可以被實際運用在哪裡,直到把運算子的「優先性」、「相依性」、「強制型轉」這三種東西兜再一起,這就是本篇文章要記錄的東西。

優先性、相依性、強制型轉

當我們把「優先性」、「相依性」、「強制型轉」這三種東西兜再一起時,就會發生一些 JavaScript 看似奇怪,但實際上非常合理的事情,但是不用擔心,因為這些東西我們都學過了。

直接看例子:

1
console.log(1 < 2 < 3); // true

合理嗎?

常識判斷「 1 小於 2 小於 3 」,正確!

那如果是這樣呢?

1
console.log(3 < 2 < 1); // true

看到這,是不是會懷疑是不是有BUG?
為什麼「3 小於 2 小於 1」是正確的?

讓我們用科學的方式來解釋它

記得「運算子的優先性」與「運算子的相依性」嗎?

讓我們查一下表格

在這個例子中,有兩個「<」代表優先性是一樣的,而「<」的相依性為「左相依」,代表最左邊的會先執行。

於是,實際過程中是這樣的:

1
2
//實際上會先執行以下判斷  
(3 < 2) // false

3 並不小於 2 因此回傳了 false ,接著原先的例子就會變成這樣

1
console.log(false < 1); // true

接著我們可能會感到更奇怪了,布林 false 如何與數值 1 比較?

這並不是預期中的型別,但仍然可以進行比較,這是因為 JavaScript 中的「強制型轉」。

「強制型轉」把布林 false 轉換成了什麼數值?

可以運用以下方法觀察

1
Number(false); // 0

看到了嗎,JavaScript 把 false 強制轉型成為數值 0 ,讓比較繼續進行

1
console.log(0 < 1); // true

因此最後輸出的結果才會是「true

懶人包:因為函式運算子執行的順序以及值的強制型轉影響

當然,也可以回頭想想文章一開始提到的例子,雖然結果與我們所想的相同,但實際上底層的運作跟我們想的並不一樣哦~

「強制型轉」的缺點

強制型轉雖然很便利,但上面的例子可以看出也有缺點,不是每個強制轉型後的情況都是可以預期的,我們先用剛剛的觀察方法觀察一些強制型轉後的變化。

1
2
3
4
Number('3'); // 3  
Number(false); // 0
Number(undefined); // NaN
Number(null); // 0

NaN (Not a Number)

表示不是數字 ,NaN 代表有個東西想轉換成數值型別,但它不是數值,所以無法轉換。以本例來說 undefined 不能轉成數值

但是,null 經過強制型轉後得到的答案是 0 ? 有符合我們的預期嗎?

我們可以透過觀察得知,並不是每次轉型結果都很明顯,這會導致相當多難以預期的 BUG。

強制轉型雖然很便利,但同時也很危險。

既然這樣不使用不就好了? 或者先檢查兩個東西是否相等?

的確可以這樣做,讓我們看看 JavaScript 運算子優先性表格。

使用「==」進行比較

好的,我們找到了程式語言相當常見的雙等號「==」,代表「檢查兩個東西是否相等」,讓我們直接來點例子:

1
2
3
4
console.log(3 == 3); // true  
console.log('3' == 3); // true
console.log(false == 0); // true
console.log(null == 0); // false

在我們知道強制轉型的概念後,大部分的例子都可以了解為什麼,但是我們剛剛不是才觀察過 null 可以被強制轉型成數值 0 嗎,怎麼在這邊是 false 呢?

有很多特殊情況並不如我們所想的那樣,來個延伸例子

1
console.log(null < 1); // true

雖然 null 會轉型為 0 ,但在某種情況下,像是在「比較」的時候並不會轉型為 0,困惑嗎?

沒錯,這造成了很多疑惑和問題。

然而我們也透過上述其他例子得知,使用「==」進行比較時,會進行強制型轉。也因為強制型轉的關係,會使得結果可能不如我們預期。這其實也被視為這個語言的缺點。

是不是開始覺得混亂了。 我也是,幸好這問題有解!

使用「===」進行嚴格比較

用三個等號比較兩個東西,就不會進行強制型轉。

使用三等號驗證剛剛使用雙等號比較的例子

1
2
3
4
console.log(3 === 3); // true  
console.log('3' === 3); // false
console.log(false === 0); // false
console.log(null === 0); // false

如果兩個值不是同個型別,就會回傳 false。此時的 JavaScript 不會進行強制型轉。

使用三等號來比較值的話,可以避免ㄧ些奇怪的潛在錯誤。在絕大多數 99.9% 的情形,我們都應該使用三個等號來比較相等性,除非你是「故意」要使用雙等號。

然而還有很多關於雙等號、三等號的比較,可以到這裡來查看。

0%