== は比べる前に型を揃えます。その変換の規則が、覚えきれないほど複雑だからです。
=== は型が違えば即座に false です。規則は1つしかありません。
覚えられない、という証明
規則を覚えようとするより、覚える価値が無いことを見たほうが早いです。
0 と '' は等しい。'' と '0' は等しくない。なのに 0 と '0' は等しい。
a == b かつ b == c なのに a == c とは限らない、ではありません。
ここではもっと悪くて、「等しい」が繋がりません。
数学の等号なら、a = b と b ≠ c なら a ≠ c のはずです。
== はそれを満たしません(推移律が成り立たない)。
繋がらない規則は、頭の中で使えません。
直感から外れる組み合わせ
配列と文字列が等しくなります。配列が文字列に変換されてから比べられるからです。
=== なら全部 false です。
== を使ってよい唯一の場面
null と undefined をまとめて判定するときだけです。
null は undefined とだけ等しく、他の何とも等しくなりません。
だから v == null は「null か undefined のどちらか」を、正確に表します。
0 も空文字も false も、そのまま通っています。
2つ目の出力で 0 と false のあいだが空いているのは、空文字が出ているためです。
!value で書くと、こうはなりません。
意味のある 0 まで「無い」にされます。
??があるならそちらを使ってください。value ?? '無い'はnullとundefinedのときだけ右を返します。== nullと同じ判定を、より短く書けます。
=== でも足りないとき
=== にも2つだけ、直感と違うところがあります。
Object.is() はこの2つを直します。
| 比べ方 | NaN と NaN |
0 と -0 |
型変換 |
|---|---|---|---|
== |
false |
true |
する |
=== |
false |
true |
しない |
Object.is() |
true |
false |
しない |
Set / includes |
true |
true |
しない |
NaN の話は別ページで詳しく扱っています。
→ なぜ NaN === NaN は false なのか
よくある誤解
「== のほうが便利」
型を揃えてくれるのは便利に見えます。ですが、揃え方をこちらで選べません。
結果は同じでも、下は何をしているか読めば分かります。
上は「== の規則がたまたまそう動いた」だけです。
変換したいなら、自分で変換してください。 → 文字列を数値に変換する
「=== は遅い」
そうではありません。=== は型が違えばそこで終わります。
== のほうが変換の手順を踏むぶん、やることが多くなります。
「文字列と数値を比べたいときは == が要る」
要りません。どちらかに揃えてから === で比べます。
自分で確かめる
上のコードは書き換えて実行できます。
0 == '\n'を試す(空白だけの文字列はどうなるか)[] == ![]を試す(両辺が変換される)null >= 0とnull == 0を並べて試す(比較と等価で規則が違う)
予想してから実行してください。 当たらないはずです。
まとめ
==は比べる前に型を揃える。その規則が複雑すぎる0 == ''と0 == '0'が真で'' == '0'は偽。「等しい」が繋がらない- 使ってよいのは
v == nullだけ。nullとundefinedをまとめて見る - ただし
??が使えるならそちらが短い ===でもNaNと-0は例外。厳密に見るならObject.is()- 型を揃えたいなら、
==に任せず自分で変換する