Javascriptのinclude()
の引数とか使い方を調べてたら、
MDNのページ(include()) に
与えられた要素が見つかるかどうかを計算するために、 SameValueZero (ゼロの同値) アルゴリズムを使用します。
と、ありましたがSameValueZero
ってなんだろうとなったので調べてみたところ、
Javascriptの比較について少し理解が深まったので記事に残しておきます。
比較について
まず、Javascriptの比較では4種類の比較がある。
以下はMDNからまとめます。
-
抽象的な等価性比較(Abstract Equality Comparison)
- ==
-
厳格な等価性比較(Strict Equality Comparison)
- ===
Array.prototype.indexOf
,Array.prototype.lastIndexOf
,case
の一致で使用
-
ゼロの同値(SameValueZero)
%TypedArray%
とArrayBuffer コンストラクター
、Map
とSet
の操作、 ES2016 で追加されたString.prototype.includes
で使用されます
-
同値(SameValue)
- 上記以外のすべての状況で使用されます
今までコードを書くのに上の2つくらいしか知らなかった。。。
イコール2つ(等価演算子)は緩い比較を行う為、意図しない挙動をすることで有名ですね。
今回はSameValueZero
とSameValue
に絞って、どんな比較か見てます。
SameValue
SameValue
から見ていくと分かりやすかったですが、
SameValue
はObject.isメソッドによって提供されています。
Object.is()
は 2 つの値が同一値を判定します。2 つの値は以下の規則の一つに当てはまる場合同一となります。
- どちらも
undefined
- どちらも
null
- どちらも
true
かどちらもfalse
- どちらも同じ文字からなる同じ長さの文字列
- どちらも同じオブジェクト
-
どちらも数で、
- どちらも
+0
- どちらも
-0
- どちらも
NaN
- あるいはどちらもゼロ以外で
NaN
でなく、同じ数値を持つ
- どちらも
パッと見るととても厳格な比較をしてくれそう。
試してみる。
Object.is('foo', 'foo'); // true
Object.is(window, window); // true
Object.is('foo', 'bar'); // false
Object.is([], []); // false
var foo = { a: 1 };
var bar = { a: 1 };
Object.is(foo, foo); // true
Object.is(foo, bar); // false
Object.is(null, null); // true
// 特殊なケース
Object.is(0, -0); // false
Object.is(-0, -0); // true
Object.is(NaN, 0/0); // true
厳密等価演算子との違いは、
NaN === NaN
がfalseになるところで、Object.is(Nan, NaN)
ではtrueになる。0 === -0
がtrueになるところObject.is(+0, -0)
では falseとなる。
SameValueZero
SameValueZero
についてMDNはこう書いています。
Same-value 等価性に似ていますが、 +0 と -0 は等しいとみなします。
以上。SameValue
を先に見たからわかりやすい。
includes()
では、このSameValueZero
による比較を行っているようです。
感想
比較はプログラムで使用頻度の高い重要な構文ですが、 比較する対象の見積もりが甘いとあっという間にバグとなります。
今回調べたObject.is()
なんかは比較する結果が分かりやすいので、
これから使っていきたいですね。
ただ、IE11以下は使えないので要Polyfillのようです。