概要
jsの比較演算子に関する仕様です。
間違って配列と数値を比較してしまいましたが、処理が通ったので驚きました。
// 比較A
1 == [1] // true
// 比較B
1 === [1] // false
// 比較C
'1' === [1] // false
種明かし
比較する値がオブジェクトの場合、手順を追ってプリミティブ型に変換した上で比較される。
解説
stack overflowでも解説をみつけましたが、概要にのせた中の比較A
を例に解説します。
解説中にプリミティブ型とオブジェクト型が出てくるので、分からない方は以下を参考に
プリミティブ型とオブジェクト型
https://qiita.com/makotoo2/items/9566cebf205ef8b42505
// 比較A
1 == [1]
1. まず、右辺がオブジェクトなので、プリミティブ型に変換。
Arrayの場合、toStringメソッドによってstringに変換。
1 == '1'
2. それでもまだ左右で型が違うので、文字列をNumberオブジェクトに変換。
1 == Number('1')
3. 右辺がオブジェクトなので、再度プリミティブ型に変換。
Numberの場合、valueOfメソッドによってintに変換
1 == 1
4. 両辺の型が揃ったので、比較し結果を返す
true
比較Bのように、比較演算子が===
の場合、1の操作までで終わり、型を揃える操作は行われずfalse
となります。
厳密な手順は少し違いますが、正確なのは上記のstack overflowでもChristophさんがおっしゃっているように、jsの規格(ECMA-spec)に載っています。
3rd edition
ECMA-spec
(P67の11.9.3 The Abstract Equality Comparison Algorithm)
また、最新版でも同様
11th edition
ECMA-spec
(P129の7.2.19 Abstract Equality Comparison)
感想
さすがjsって感じの親切さですね。もちろん、この仕様に頼るとバグの元になる上に、読む人に理解されづらいので、自身のコードは別の書き方に修正しました。
また、jsの規格も初めて読みましたが結構簡単な英語で書かれているので、読みやすかったです。