オブジェクト比較の落とし穴:厳格な等価性比較 (===) と浅い比較 (==) の違い
JavaScriptにおけるオブジェクト比較
厳格な等価性比較 (===)
厳格な等価性比較は、オブジェクトの参照が一致する場合にのみtrueを返します。つまり、以下の条件を満たす場合のみtrueになります。
- オブジェクトが同じ型であること
- オブジェクトのプロパティ名が完全に一致すること
以下は、厳格な等価性比較の例です。
const obj1 = {
name: 'John Doe',
age: 30,
};
const obj2 = {
name: 'John Doe',
age: 30,
};
console.log(obj1 === obj2); // false
const obj3 = obj1;
console.log(obj1 === obj3); // true
上記のように、obj1
とobj2
は同じ値を持つオブジェクトですが、異なる参照を持つため、厳格な等価性比較ではfalseとなります。一方、obj3
はobj1
への参照を持つため、trueとなります。
浅い比較 (==)
浅い比較は、オブジェクトのプロパティ名と値が一致する場合にのみtrueを返します。ただし、プロパティの順序やプロパティの型は考慮されません。
const obj1 = {
name: 'John Doe',
age: 30,
};
const obj2 = {
age: 30,
name: 'John Doe',
};
console.log(obj1 == obj2); // true
const obj3 = {
name: 'John Doe',
age: 31,
};
console.log(obj1 == obj3); // false
上記のように、obj1
とobj2
はプロパティ名と値が一致するため、浅い比較ではtrueとなります。一方、obj3
はage
プロパティの値が異なるため、falseとなります。
深い比較は、オブジェクトのプロパティ名、値、型、順序がすべて一致する場合にのみtrueを返します。
深い比較を行うには、ライブラリや自作の関数を使用する必要があります。代表的なライブラリには、以下のものがあります。
const obj1 = {
name: 'John Doe',
age: 30,
address: {
city: 'Tokyo',
country: 'Japan',
},
};
const obj2 = {
name: 'John Doe',
age: 30,
address: {
country: 'Japan',
city: 'Tokyo',
},
};
const isEqual = require('lodash.isEqual');
console.log(isEqual(obj1, obj2)); // true
上記のように、obj1
とobj2
はプロパティ名、値、型、順序がすべて一致するため、深い比較ではtrueとなります。
その他の比較方法
上記以外にも、オブジェクトを比較する方法はいくつかあります。
- 特定のプロパティのみを比較する
- オブジェクトの値を文字列に変換して比較する
これらの方法は、比較したいオブジェクトの性質や用途によって使い分ける必要があります。
JavaScriptでオブジェクトを比較するには、いくつかの方法があります。それぞれの方法にはメリットとデメリットがあり、比較したいオブジェクトの性質や用途によって使い分ける必要があります。
厳格な等価性比較 (===)
const obj1 = {
name: 'John Doe',
age: 30,
};
const obj2 = {
name: 'John Doe',
age: 30,
};
console.log(obj1 === obj2); // false
const obj3 = obj1;
console.log(obj1 === obj3); // true
浅い比較 (==)
const obj1 = {
name: 'John Doe',
age: 30,
};
const obj2 = {
age: 30,
name: 'John Doe',
};
console.log(obj1 == obj2); // true
const obj3 = {
name: 'John Doe',
age: 31,
};
console.log(obj1 == obj3); // false
深い比較
const obj1 = {
name: 'John Doe',
age: 30,
address: {
city: 'Tokyo',
country: 'Japan',
},
};
const obj2 = {
name: 'John Doe',
age: 30,
address: {
country: 'Japan',
city: 'Tokyo',
},
};
const isEqual = require('lodash.isEqual');
console.log(isEqual(obj1, obj2)); // true
その他の比較方法
特定のプロパティのみを比較する
const obj1 = {
name: 'John Doe',
age: 30,
};
const obj2 = {
name: 'Jane Doe',
age: 30,
};
function compareName(obj1, obj2) {
return obj1.name === obj2.name;
}
console.log(compareName(obj1, obj2)); // false
オブジェクトの値を文字列に変換して比較する
const obj1 = {
name: 'John Doe',
age: 30,
};
const obj2 = {
name: 'John Doe',
age: 30,
};
const obj1Str = JSON.stringify(obj1);
const obj2Str = JSON.stringify(obj2);
console.log(obj1Str === obj2Str); // true
オブジェクトをJSONに変換して比較する
const obj1 = {
name: 'John Doe',
age: 30,
};
const obj2 = {
name: 'John Doe',
age: 30,
};
const obj1Json = JSON.parse(JSON.stringify(obj1));
const obj2Json = JSON.parse(JSON.stringify(obj2));
console.log(obj1Json === obj2Json); // true
オブジェクト比較のその他の方法
自作の関数
function compareObjects(obj1, obj2) {
// プロパティ名の比較
if (Object.keys(obj1).length !== Object.keys(obj2).length) {
return false;
}
for (const prop in obj1) {
// プロパティが存在しない場合
if (!obj2.hasOwnProperty(prop)) {
return false;
}
// 値の比較
if (typeof obj1[prop] === 'object') {
// オブジェクトの場合は再帰的に比較
if (!compareObjects(obj1[prop], obj2[prop])) {
return false;
}
} else if (obj1[prop] !== obj2[prop]) {
// 値が異なる場合
return false;
}
}
return true;
}
この関数は、以下のことを行います。
- オブジェクトのプロパティがオブジェクトの場合は、再帰的に比較します。
ライブラリの利用
Lodashなどのライブラリには、オブジェクト比較用の関数が用意されています。
const isEqual = require('lodash.isEqual');
const obj1 = {
name: 'John Doe',
age: 30,
};
const obj2 = {
name: 'John Doe',
age: 30,
};
console.log(isEqual(obj1, obj2)); // true
LodashのisEqual
関数は、以下のことを行います。
比較対象の性質に合わせた方法
オブジェクト比較には様々な方法があり、それぞれメリットとデメリットがあります。比較対象の性質や用途に合わせて最適な方法を選択する必要があります。
- 比較したいオブジェクトが単純な値を持つ場合は、厳格な等価性比較 (===) や浅い比較 (==) で十分です。
- 比較したいオブジェクトが複雑な構造を持つ場合は、深い比較が必要になります。
- 特定のプロパティのみを比較したい場合は、自作の関数を作成する必要があります。
- オブジェクト比較を頻繁に行う場合は、ライブラリの利用を検討すると良いでしょう。
javascript object comparison