私たちは数学にある多くの比較演算子を知っています。:
JavaScript では、次のような記述します:
- より大きい/より小さい:
a > b
,a < b
- 大きい/小さいまたは等しい:
a >= b
,a <= b
. - 等位チェックは
a == b
として書かれます(2重の等式記号'='
に注意してください。1つの記号a = b
は代入を意味します。) - 等しくない。数学において、この記法は
≠
です。JavaScriptにおいては、感嘆符がその前についた代入として書かれます:a != b
.
この記事では、異なる比較のタイプに関して、JavaScript ではどうやるか、またその重要な特性について詳しく学んでいきます。
記事の末尾には “JavaScriptの癖” に関連する問題を回避するための良いレシピがあります。
Boolean は結果です
すべての比較演算子はブール値を返します:
true
– “はい”, “正しい” もしくは “真” を意味します.false
– “いいえ”, “誤り” もしくは “偽” を意味します.
例:
alert( 2 > 1 ); // true (正しい)
alert( 2 == 1 ); // false (誤り)
alert( 2 != 1 ); // true (正しい)
任意の値のように、比較結果は変数に代入することができます:
let result = 5 > 4; // 比較の結果を代入
alert( result ); // true
文字列比較
どちらの文字列がより大きいかを見る場合、いわゆる “辞書” もしくは “数学における辞書式順序” の順序が使われます。
言い換えると、文字列は文字単位で比較されます。
例:
alert( 'Z' > 'A' ); // true
alert( 'Glow' > 'Glee' ); // true
alert( 'Bee' > 'Be' ); // true
2つの文字列を比較するアルゴリズムはシンプルです:
- 両方の文字列の最初の文字を比較します。
- 1つ目のほうが大きい(もしくは小さい)場合、1つ目の文字列は2つ目の文字列よりも大きい(もしくは小さい)です。それで完了です。
- そうではなく、もしも最初の文字が等しい場合は、同じ方法で2つ目の文字を比較します。
- 文字列の最後までそれを繰り返します。
- 両方の文字列が同時に終わった場合、それらは等しいです。そうでなければ長い文字列がより大きいです。
上の例において、比較 'Z' > 'A'
は最初のステップで結果を得ます。
文字列 "Glow"
と "Glee"
は文字単位の比較がされます。
G
はG
と同じ.l
はl
と同じ.o
はe
より大きい. ここでストップ. 1つ目の文字列のほうが大きいです.
上で与えられている比較アルゴリズムは、本の辞書や電話帳で使われているのとおおよそ同じです。しかし全く同じではありません。
例えば、大文字小文字の問題。大文字 "A"
は小文字の "a"
とは同じではありません。どちらがより大きいでしょう?実際は、小文字 "a"
です。なぜでしょう?なぜなら、小文字は内部のエンコーディングテーブル(Unicode)でより大きな値を持っているからです。チャプター 文字列 で具体的な詳細と結果を取り上げます。
異なる型の比較
異なる型に所属している値を比較するとき、それらは数値に変換されます。
例:
alert( '2' > 1 ); // true, 文字列 '2' は数値 2 になります
alert( '01' == 1 ); // true, 文字列 '01' は数値 1 になります
真偽値の場合、true
は 1
になり、 false
は 0
になります。:
例:
alert( true == 1 ); // true
alert( false == 0 ); // true
次の2つが同時に発生する場合があります:
- 2つの値が等しい
- それらの一方は真偽値の
true
で、もう一方は真偽値のfalse
例:
let a = 0;
alert( Boolean(a) ); // false
let b = "0";
alert( Boolean(b) ); // true
alert(a == b); // true!
JavaScriptの立場からすると、それは普通です。等価チェックは数値変換を使って変換をします(したがって、"0"
は 0
になります)。一方、 明示的な Boolean
変換は別のルールセットを利用します。
厳密な等価
通常の等価チェック "=="
は問題を持っています。0
と false
を異なるものと判断させることはできません:
alert( 0 == false ); // true
空文字列でも同じです:
alert( '' == false ); // true
これは、異なる型のオペランドは等価演算子 ==
によって数値に変換されるためです。空文字は、ちょうど false
のように 0 になります。
もしも 0
と false
を分けたい場合、どうすべきでしょうか?
厳密等価演算子 ===
は型変換なしで等価をチェックします。
言い換えると、もしも a
と b
が異なる型の場合、a === b
はそれらの変換の試みをすることなく、すぐに false
を返します。
試してみましょう:
alert( 0 === false ); // false, 型が異なるためです
!=
の類似として、“厳密な非等価” 演算子 !==
も存在します。
厳密等価チェック演算子は書くのが少し長いですが、起こっていることを明らかにし、エラーの余地を少なくします。
null と undefined の比較
null
もしくは undefined
が他の値と比較される場合、非直感的な振る舞いになります。
- 厳密な等価チェック
===
の場合 -
それぞれが自身の別々の型に所属しているため、これらの値は異なります。
alert( null === undefined ); // false
- 非厳密なチェック
==
の場合 -
特別なルールがあります。この2つは “スイートカップル” と呼ばれ、(
==
の意味で)等しくなりますが、これら以外の値とは等しいと扱われることはありません。alert( null == undefined ); // true
- 数学や他の比較
< > <= >=
-
値
null/undefined
は数値に変換されます:null
は0
になり、undefined
はNaN
(Not a Number)になります。
今、それらのルールを適用した時に起こる面白いことを見てみましょう。そして、より重要なことはこれらの機能でトラップに陥らない方法です。
奇妙な結果: null vs 0
null
とゼロを比較してみましょう:
alert( null > 0 ); // (1) false
alert( null == 0 ); // (2) false
alert( null >= 0 ); // (3) true
上の3つの例は数学的には奇妙です。最後の結果は “null
はゼロより大きいまたは等しい” ことを述べています。そうであれば上2つの比較のどちらかは正しくなければいけませんが、両方とも false です。
その理由は等価チェック ==
と比較 > < >= <=
は異なった処理するためです。比較は null
を数値に変換します、したがって 0
として扱います。そういう訳で (3) null >= 0
は true で、 (1) は false になります。
一方、undefined
と null
の等価チェック ==
はいずれの変換もなしにルールによって処理します。それらはお互い等価で他のいずれとも等価ではありません。なので (2) null == 0
は false です。
比べるものがない undefined
値 undefined
は比較に関与しません。:
alert( undefined > 0 ); // false (1)
alert( undefined < 0 ); // false (2)
alert( undefined == 0 ); // false (3)
なぜそこまでゼロが嫌いなのでしょう?常に false です!
このような結果になった理由は次の通りです:
- 比較
(1)
と(2)
は、undefined
はNaN
に変換されるためfalse
を返します。また、NaN
はすべての比較でfalse
を返す特別な数値です。 undefined
はnull
とのみ等価で、それ以外とは等価ではないため、等価チェック(3)
はfalse
を返します。
問題を回避する
なぜこれらの例を見てきたのでしょう?常にこれらの特殊性を覚えておく必要があるでしょうか?そうではありません。実際には、これらのトリッキーなことは徐々に馴染みの深いものになっていくでしょう。ですが、問題を回避するための確実な方法があります。
- 厳密な等価
===
以外の比較演算子については、例外的な注意を払ってundefined/null
の比較を行ってください。 - 本当に正しい場合でない限り、
null/undefined
かもしれない変数に対して比較>= > < <=
は使ってはいけません。変数がこのような値を持つ可能性がある場合は、それらを別々にチェックしてください。
サマリ
- 比較演算子は論理値を返します。
- 文字列は "辞書” 順で、1文字ずつ比較されます。
- 異なった型の値が比較される場合、それらは数値に変換されます(厳密な等価チェックを除く)
- 値
null
とundefined
はそれぞれ等価==
であり、それ以外の値とは等価ではありません。 >
または<
のような比較を、null/undefined
になる可能性のある変数に対して使う場合は注意してください。null/undefined
を別々にチェックするのが良いアイデアです。
コメント
<code>
タグを使ってください。複数行の場合は<pre>
を、10行を超える場合にはサンドボックスを使ってください(plnkr, JSBin, codepen…)。