Get to know MDN better
このページはコミュニティーの尽力で英語から翻訳されました。MDN Web Docs コミュニティーについてもっと知り、仲間になるにはこちらから。
JavaScript には、異なる値の比較演算が 3 つあります。
どの演算子を使用するかは、どのような比較を行いたいかに依存します。簡単に言えば、
これらは、JavaScript における 4 つの等価性アルゴリズムのうち、3 つに対応します。
なお、これらの区別はプリミティブ値の扱いについてのことです。いずれの場合も引数が概念的に似た構造を持つかどうかを比較する訳ではありません。プリミティブ値ではない x および y オブジェクトが同一の構造を持っていてもオブジェクトが異なれば、上記のいずれの形でも false と評価されます。
厳密な等価性は、2 つの値が等しいか比較します。比較対象の値はどちらも、比較する前に別の値へ暗黙のうちに変換されることはありません。値が異なる型の場合、それらの値は等しくないとみなします。値が同じ型で数値ではない場合、同じ値であれば等しいとみなします。最後に、どちらの値も数値である場合、どちらも NaN ではなく同じ値である、あるいは一方が +0 かつもう一方が -0 であるときに等しいとみなします。
厳密な等価性は、たいていの使い方で正しい比較になります。数値以外のあらゆる値において、これは「値が自分自身と等しい」という明快な解釈を用います。数値においては、2つの極めて特殊なケースを扱えるようにわずかに異なる解釈を用います。1つ目は浮動小数点数の 0 には正と負の符号付きが存在することです。これは、ある種の数学的な解を表すために役立ちますが、ほとんどの場合は +0 と -0 の違いを意識せず、厳密な等価性ではこれらを同じ値として扱います。2つ目は浮動小数点数には非数 NaN の概念があることです、これは例えば正の無限大に負の無限大を加算するといった一定の数学的に明確ではない問題達の解を表します。厳密な等価性では NaN を他のどの値 (自分自身も含む) とも等しくないものとして扱います。((x !== x) が true になる唯一の場合は x が NaN である場合です。)
また、=== 以外にも厳密な等価性は配列のインデックスを探すメソッドで使用されます。Array.prototype.indexOf()、Array.prototype.lastIndexOf()、TypedArray.prototype.indexOf()、TypedArray.prototype.lastIndexOf()、case での比較です。つまり、indexOf(NaN) を使用して配列の NaN 値のインデックスを探したり、NaN を switch 文の case 値として使用して何かと一致させることはできません。
緩い等価性は対称的です。(変換の順序を除いて) A と B の値が何であっても、A == B は常に B == A と同じ意味づけになります。== を使用して緩い等価性を実行する場合の動作は以下の通りです。
伝統的に、そして ECMAScript によれば、すべてのプリミティブとオブジェクトは undefined および null と緩い不等価であるとされています。しかし、ほとんどのブラウザーは、あるコンテキストにおいて、非常に狭いクラスのオブジェクト(具体的には、あらゆるページの document.all オブジェクト)が、あたかも undefined という値を持つかのように振る舞うことを許可しています。緩い等価性はそのようなコンテキストの 1 つです。null == A と undefined == A は、A が undefined をエミュレートするオブジェクトである場合にのみ真と評価されます。他に、オブジェクトが undefined や null と緩やかな等価性を持つことはありません。
ほとんどの場合、緩い等価性を使用することは推奨されません。厳密な等価性を用いた比較の結果は予測しやすく、型変換がないため、よりすばやく評価できる可能性があります。
次の例は、数値プリミティブ 0、長整数プリミティブ 0n、文字列プリミティブ '0'、toString() の値が '0' であるオブジェクトを含む緩い等価性の比較を示しています。
緩い等価性は、 == 演算子でのみ使用されます。
同値等価性は、すべての状況で 2 つの値が機能的に同一かを判断します(この用法はリスコフの置換原則の実践例と言えます)。例として、変更不可のプロパティを変化させようとした場合を見てみましょう。
変更不可のプロパティを変更しようとしたとき、Object.defineProperty は例外を発生させますが、実際の変更が要求されなかった場合は何もしません。v が -0 であれば、変更が要求されていないので、エラーは発生しません。内部的には、変更不可のプロパティが再定義された場合、新たに指定された値と現在の値が同値等価性によって比較されます。
同値等価性は Object.is メソッドによって提供されます。等価な同一性を持つ値が期待される場合、言語上のほとんどの場所で使用されます。
同値等価性に似ていますが、+0 と -0 は等しいとみなします。
同値ゼロ等価性 (Same-value-zero equality) は JavaScript API として公開されていませんが、独自のコードで実装することができます。
同値ゼロは NaN を等価に扱うという点で厳密な等価性と異なり、-0 を 0 と等価に扱うことのみが同値等価性と異なります。これは特に NaN を扱う場合、検索時に最も賢明な動作をするようになります。Array.prototype.includes()、TypedArray.prototype.includes()、またキーの等価性を比較するために Map や Set のメソッドで使用されます。
二重等号と三重等号を比較するとき、一方は他方を「拡張した」ものである言われがちです。例えば、二重等号は三重等号と同じことをすべて行うだけでなくオペランドの型変換も行うことから、三重等号を拡張したものであると聞いたことがあるかもしれません。例えば、6 == "6" となります。あるいは二重等号が基本形であり、三重等号は 2 つのオペランドが同一の型であることを要求するという制約を加えていることから、三重等号が拡張形であると言われたかもしれません。
しかし、この考え方は、等価性の比較が一次元の「スペクトル」を形成し、「完全に厳密な」ものが一端にあり、「完全に緩い」ものが他にもあることを意味します。このモデルはObject.isでは不十分で、二重等号よりも「緩い」、三重等号よりも「厳しい」ものではなく、その中間(つまり、二重等号よりも厳しく、三重等号よりも緩い)にも当てはまらないからです。同一性を比較した以下の表から、Object.is が NaN を扱う方法が原因であることがわかります。Object.is(NaN, NaN) が false に評価されるのであれば、-0 と +0 を区別することにより、三重等号より厳密であることから緩い/厳密のスペクトルに含めることができることに注目してください。しかし NaN の扱いは、これが正しくないことを表します。残念ながら、Object.is は等価演算子に関する緩さや厳密さではなく、単純に固有の特性の観点から考えなければなりません。
| undefined | undefined | ✅ true | ✅ true | ✅ true | ✅ true |
| null | null | ✅ true | ✅ true | ✅ true | ✅ true |
| true | true | ✅ true | ✅ true | ✅ true | ✅ true |
| false | false | ✅ true | ✅ true | ✅ true | ✅ true |
| 'foo' | 'foo' | ✅ true | ✅ true | ✅ true | ✅ true |
| 0 | 0 | ✅ true | ✅ true | ✅ true | ✅ true |
| +0 | -0 | ✅ true | ✅ true | ❌ false | ✅ true |
| +0 | 0 | ✅ true | ✅ true | ✅ true | ✅ true |
| -0 | 0 | ✅ true | ✅ true | ❌ false | ✅ true |
| 0n | -0n | ✅ true | ✅ true | ✅ true | ✅ true |
| 0 | false | ✅ true | ❌ false | ❌ false | ❌ false |
| "" | false | ✅ true | ❌ false | ❌ false | ❌ false |
| "" | 0 | ✅ true | ❌ false | ❌ false | ❌ false |
| '0' | 0 | ✅ true | ❌ false | ❌ false | ❌ false |
| '17' | 17 | ✅ true | ❌ false | ❌ false | ❌ false |
| [1, 2] | '1,2' | ✅ true | ❌ false | ❌ false | ❌ false |
| new String('foo') | 'foo' | ✅ true | ❌ false | ❌ false | ❌ false |
| null | undefined | ✅ true | ❌ false | ❌ false | ❌ false |
| null | false | ❌ false | ❌ false | ❌ false | ❌ false |
| undefined | false | ❌ false | ❌ false | ❌ false | ❌ false |
| { foo: 'bar' } | { foo: 'bar' } | ❌ false | ❌ false | ❌ false | ❌ false |
| new String('foo') | new String('foo') | ❌ false | ❌ false | ❌ false | ❌ false |
| 0 | null | ❌ false | ❌ false | ❌ false | ❌ false |
| 0 | NaN | ❌ false | ❌ false | ❌ false | ❌ false |
| 'foo' | NaN | ❌ false | ❌ false | ❌ false | ❌ false |
| NaN | NaN | ❌ false | ❌ false | ✅ true | ✅ true |
一般的に、Object.is のゼロに対する特別な動作が関心の対象になりえると思われるのは、ある種のメタプログラミング方式に則る時、特にプロパティ記述子に関して Object.defineProperty の特徴の一部を再現したい時に限られます。このような要件が必要ないのであれば、Object.is ではなく === を使用してください。2 つの NaN 値を比較した結果が true になることが必要な場合であっても、通常は、NaN をチェックして特別扱いする方が (前バージョンの ECMAScript からは isNaN メソッドを使えます) 、比較処理中に現れた全てのゼロについてその符号が周囲の処理からどう影響されるのか悩むよりも簡単です。
すべてを網羅してはいませんが、-0 と +0 の区別が発生する可能性がある内蔵メソッドや演算子を以下に示します。コード中ではこれらを考慮して下さい:
- (単項否定演算子)以下例を考えてみてください。
obj.velocity が 0 である (あるいは計算結果が 0 になる) とき、そこで -0 が生成されて stoppingForce に伝播します。
Math.atan2, Math.ceil, Math.pow, Math.round引数に -0 が存在しなくても、場合によってはこれらのメソッドの返値として -0 が式に取り込まれる可能性があります。例えば、負の値の累乗で -Infinity が発生するように Math.pow を使用したとき、奇数の指数は -0 に評価されます。それぞれのメソッドのドキュメントを確認してください。
Math.floor, Math.max, Math.min, Math.sin, Math.sqrt, Math.tan引数のひとつが -0 である場合に、これらのメソッドから -0 を返値として得る可能性があります。例えば、Math.min(-0, +0) は -0 になります。それぞれのメソッドのドキュメントを確認してください。
~, <<, >>これらの演算子は、内部で ToInt32 アルゴリズムを使用します。内部の 32 ビット整数型は 0 の表現が 1 種類しかないため、逆の演算を行った後に -0 は戻らないでしょう。例えば Object.is(~~(-0), -0) や Object.is(-0 << 2 >> 2, -0) は、false になります。
ゼロの符号を考慮していない場合に、Object.is に頼ることは危険でしょう。もちろん -0 と +0 を区別する意図があれば、これはまさに望むことです。
Object.is の仕様書では、すべての NaN のインスタンスを同じオブジェクトとして扱っています。しかし、型付き配列が利用でき、インスタンスを区別することができるので、次の例のようにすべてのコンテキストで同じ動作をするとは限りません。
This page was last modified on 2026年3月21日 by MDN contributors.
Your blueprint for a better internet.
Visit Mozilla Corporation’s not-for-profit parent, the Mozilla Foundation.
Portions of this content are ©1998–2026 by individual mozilla.org contributors. Content available under a Creative Commons license.