jsでオブジェクトを比較する
ふと、オブジェクトを比較した時に、同じはずなのに違うと言われたのでその内容を改めて確認してみた。
今回何をしていたかというと、元々Dateオブジェクトを利用している箇所を改めて、dayjsに置き換えるというタスクに取り掛かる時にデグレが発生していないかを担保する必要があった。
その際に前のdateオブジェクトで作成したものと今回利用するdayjs.toDateしたオブジェクトを単純に===で比較すればいいやと思ってそうしてみるとうまく行かない。。
、
===
演算子を使用して日付オブジェクトを比較していることが問題です。JavaScript では、オブジェクト(Date オブジェクトを含む)は参照によって比較されます。つまり、同じ時刻を表していても、異なるオブジェクトであればfalse
を返します。
そうするとこのような記述を見つけた。
つまり、オブジェクトを比較するとメモリが異なる場所にあるため、怒られている。
同じDate型だとしても異なるメモリ領域に保存されており、その場合今回の等価演算子を用いるとうまく行かない。
プリミティブ型の場合はどうだろうか?
const a = 'test'
const b = 'test'
console.log(a === b)
このようにすると、trueが返ってきた。
つまり、オブジェクトだと参照が比較されていて、プリミティブだと値で比較されているということになる。
JavaScriptでは、プリミティブ型とオブジェクト(参照型)で比較の仕方が異なる。
プリミティブ型の場合、値が直接比較されます。 つまり、二つのプリミティブ型の変数を比較すると、それぞれの変数が保持する値が同じかどうかがチェックされます。
オブジェクト(参照型)の場合、参照先が比較されます。 これは、変数が保持しているのは実際のデータではなく、データが格納されている場所のアドレスであるためです。そのため、二つのオブジェクト型の変数を比較すると、それぞれの変数が同じアドレスを参照しているかどうかがチェックされます。
プリミティブ型: 例えば、let a = 10; と let b = 10; のように変数 a と b に同じ値 10 を代入した場合、 a === b は true となります。これは、a と b が共に値 10 を直接保持しているためです。
オブジェクト型: 一方で、 const arr1 = ["ichiro"]; と const arr2 = ["ichiro"]; のように、同じ要素を持つ配列を異なる変数 arr1 と arr2 に代入した場合、 arr1 === arr2 は false となります。これは、 arr1 と arr2 はそれぞれ異なるアドレスに格納された配列を参照しているためです。
この違いは、 const による宣言と合わせて考えると理解が深まります。 const で宣言された変数は再代入できませんが、オブジェクト型の場合は参照先のアドレスが固定されるだけで、参照先のデータ自体は変更可能です。 例えば、 const arr =; と宣言した後でも、 arr.push(4); のように配列の要素を追加することができます。
このように、JavaScriptではプリミティブ型とオブジェクト型でデータの保持方法や比較方法が異なるため、注意が必要です。
Discussion