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のようです。
