私たちは数学で多くの比較演算子を知っています。
JavaScriptでは、それらは次のように書かれます。 a > b
, a < b
.
a >= b
, a <= b
.a == b
、二重の等号==
は等号検定を意味し、単一の等号a = b
は代入を意味することに注意してください。この記事では、さまざまなタイプの比較について、JavaScript がどのように比較を行うのか、重要な特殊性を含めて詳しく学びます。
最後には、「JavaScript の癖」関連の問題を避けるための良いレシピを見つけるでしょう。
Boolean is the result
All comparison operators return a boolean value:
-
true
– “yes”, “correct” or “the truth”. -
false
– “no”, “wrong” or “not the truth” という意味の比較演算子です。
例:
alert( 2 > 1 ); // true (correct)alert( 2 == 1 ); // false (wrong)alert( 2 != 1 ); // true (correct)
比較結果は他の値と同じように変数に代入することができる。
let result = 5 > 4; // assign the result of the comparisonalert( result ); // true
String comparison
文字列が他のものより大きいかどうかを見るために、JavaScript ではいわゆる「辞書」または「辞書順」が使用されています。
言い換えれば、文字列は文字ごとに比較されます。
alert( 'Z' > 'A' ); // truealert( 'Glow' > 'Glee' ); // truealert( 'Bee' > 'Be' ); // true
二つの文字列を比較するアルゴリズムは簡単です:
- 両方の文字列の最初の文字を比較する。
- 最初の文字列の最初の文字がもう一方の文字列のものよりも大きい(または小さい)場合、最初の文字列は2番目の文字列よりも大きい(または小さい)ことになります。
- そうでない場合、両方の文字列の最初の文字が同じなら、同じように2番目の文字を比較する。
- どちらかの文字列が終わるまで繰り返す。 そうでなければ、長い方の文字列が大きい。
上の最初の例では、比較'Z' > 'A'
は最初のステップで結果に到達する。
2番目の比較 'Glow'
と 'Glee'
は文字列が1文字ずつ比較されるので、より多くのステップが必要です。
-
G
はG
と同じです。 -
l
はl
と同じです。 -
o
はe
より大きいですね。 ここでストップ。 最初の文字列の方が大きい。
上で与えられた比較アルゴリズムは、辞書や電話帳で使われているものと大体同じですが、全く同じではありません。
例えば、大文字と小文字は重要です。 大文字の"A"
と小文字の"a"
は同じではありません。 どちらが大きいか? 小文字の"a"
です。 なぜか? JavaScriptが使っている内部エンコーディングテーブル(Unicode)では、小文字の方が大きなインデックスを持っているからです。 この具体的な詳細と結果については、「文字列」の章で説明します。
異なる型の比較
異なる型の値を比較するとき、JavaScriptはその値を数値に変換します。
例えば、
alert( '2' > 1 ); // true, string '2' becomes a number 2alert( '01' == 1 ); // true, string '01' becomes a number 1
ブール値の場合、true
は1
、false
は0
となります。
例えば:
alert( true == 1 ); // truealert( false == 0 ); // true
同時に:
- 二つの値が等しいことがあり得ます。
- 一方はブール値として
true
、もう一方はブール値としてfalse
。
例えば:
let a = 0;alert( Boolean(a) ); // falselet b = "0";alert( Boolean(b) ); // truealert(a == b); // true!
JavaScriptの立場からはこの結果はごく普通のことです。
Strict equality
通常の等値検査 ==
には問題があります。 それは0
とfalse
を区別できない:
alert( 0 == false ); // true
空文字列でも同じことが起こる。
alert( '' == false ); // true
これは、異なる型のオペランドが等号演算子 ==
によって数値に変換されるために起こることです。 空の文字列はfalse
と同じく0になります。
0
とfalse
を区別したい場合はどうすればよいでしょうか。
厳格な等式演算子===
は、型変換をせずに等式をチェックします。
つまり、a
とb
が異なる型であれば、a === b
は変換を試みずに直ちにfalse
を返します。
試してみよう:
alert( 0 === false ); // false, because the types are different
また、!=
に類似した「厳格な非等号」オペレータ!==
が存在する。
厳密な等式演算子は書くのが少し長くなりますが、何が起こっているかが明白になり、エラーの余地が少なくなります。
ヌルと未定義の比較
null
やundefined
が他の値と比較されたときに直観的ではない挙動があります。
厳密な等式チェックの場合 ===
これらの値はそれぞれ異なる型だからです。
alert( null === undefined ); // false
厳密ではないチェックの場合 ==
特別な規則があるのです。 この2つは「スイート・カップル」です。互いに(==
の意味で)等しくなりますが、他の値にはなりません。
alert( null == undefined ); // true
数学や他の比較のために < > <= >=
null/undefined
は数字に変換されます。 null
は 0
に、undefined
は NaN
になります。
さて、これらのルールを適用すると、おかしなことが起こるので、見てみましょう。
Strange result: null vs 0
それでは、null
と0を比較してみましょう:
alert( null > 0 ); // (1) falsealert( null == 0 ); // (2) falsealert( null >= 0 ); // (3) true
数学的におかしいですね。 最後の結果は「null
は0以上である」と述べているので、上の比較のどちらかではtrue
であるはずですが、どちらも偽です。
その理由は、等値検査==
と比較> < >= <=
は異なる動作をするからです。 比較はnull
を数値に変換し、0
として扱います。 そのため、(3)null >= 0
は真、(1)null > 0
は偽となります。
一方、undefined
とnull
の等号チェック==
は、変換がなければ互いに等しく、それ以外は等しくないように定義されています。 だから(2)null == 0
は偽なのです。
比較できない未定義
値undefined
は他の値と比較してはいけない:
alert( undefined > 0 ); // false (1)alert( undefined < 0 ); // false (2)alert( undefined == 0 ); // false (3)
なぜそんなにゼロが嫌なのでしょうか:
<7405> <4860> なぜこんなに嫌なの
- 比較
(1)
と(2)
はfalse
を返します。これはundefined
がNaN
に変換され、NaN
がすべての比較でfalse
を返す特別な数値になるためです。 - 等号チェック
(3)
はfalse
を返します。なぜならundefined
はnull
,undefined
と等しいだけで、他の値はないからです。
問題を避ける
なぜこれらの例を見て行ったのでしょうか。 このような特殊性を常に覚えておく必要があるのでしょうか。 そうではありません。 実際、これらのトリッキーなことは時間とともにだんだん慣れてくるものですが、これらの問題を避けるための確実な方法があります:
- Treat any comparison with
undefined/null
except the strict equality===
with exceptional care. - Don’t use comparisons
>= > < <=
with a variable that may benull/undefined
, unless you’re really sure of what you’re doing.All for the way with these problems with the same way is a certain way to avoid problems.
概要
- 比較演算子はブール値を返します。
- 文字列は「辞書」順で文字ごとに比較されます。
- 異なる型の値が比較されるとき、それらは数値に変換されます (厳密な等価検査を除く)。
- 値
null
とundefined
は互いに==
と等しく、他のどの値とも等しくはなりません。 - 時折
null/undefined
になる可能性がある変数と>
や<
などの比較を使うときは注意が必要です。null/undefined
を個別にチェックするのが良いでしょう。