javascriptでは、いくつかの等価性判定の演算子、メソッドがある。
等価性判定の方法をざっと纏めておく。
参考:等価性の比較と同一性
文字列、数値、真偽値
等価演算子「==」だと、型が異なる場合には暗黙の型変換をして判定される。
等価演算子では、抽象等価比較アルゴリズムを用いて比較するらしいが、この辺を意識してプログラムを組むのも難しいので、通常 「==」は用いない。
厳密等価演算子「===」を用いるのが一般的。
null
厳密等価演算子「===」で比較。
等価演算子だと、undefinedでもnullと等価だと判定されちゃう。
非数
NaN(非数、Not a Number)の場合には厳密等価演算子でもfalseになること。
しようがないので、別のやり方で判定する必要がある。
そこで、isNaN関数があるので、それを用いることにしようとしても、ここでも暗黙の型変換の罠がある。
厳密なNaNの判定については、Number.isNaNで行う。
なお、配列のメソッドで非数が判定できないことがあるので注意。
配列(要素がプリミティブ値のみの場合)
等価演算子、厳密等価演算子だと参照の比較(同一性判定)なので、要素の中身の比較はされない。
なので、中身の比較をして等価性判定するためにはちょっと工夫が必要。
for文で要素の中身を比較して頑張ろうとすると、以下になる。
もっと簡単に、JSON.stringifyで文字列に直して比較しても大体OKなのだが、NaN、undefined、InfinityなどのJSONに対応していない値はnullに変換されてしまうため、厳密にそれらを区別したい場合は注意が必要。
オブジェクト(要素がプリミティブ値のみの場合)
無効なJSON値(NaN、undefined、Infinity)が要素に無ければ、JSON.stringifyで文字列に変換しての比較でいいのだが、そのまま比較するだけではキーの順序が揃っているもののみが等価と判定されてしまう。
Object.entriesでキーと値の配列に変換して、ソートした後、JSON.stringifyで比較すると、キーの順序が揃ってなくても等価と判定できる。
無効なJSON値が含まれてて、厳密に判定したければ、リストの場合と同じようにfor文で要素を比較して頑張る。
一般的な配列、オブジェクト
オブジェクトの要素がオブジェクトや配列だったり、配列の要素がオブジェクトだったりを考慮する場合、ここまでの応用でできないことはないが、ライブラリを使う方が安全。
lodash もしくは underscorejsで isEqual関数が提供されている。
おわりに
- 非数NaNの扱いには注意。
- 配列やオブジェクトの比較は、だいたいはJSON.stringifyでOK(オブジェクトの場合はキー順序を考慮する必要あり)。ただし、無効なJSON値(NaN、undefined、Infinity)が要素に含まれている場合は注意。
- より一般的な配列やオブジェクトの比較は、lodash もしくは underscorejsで比較すればよい。
以上です。