私たちは数学にある多くの比較演算子を知っています。:
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…)。