2 分钟阅读
JS 中如何比较两个对象是否相等
在JavaScript中,我们处理有关对象的业务逻辑的时候,你可能见过这种奇怪的现象:

即使两个不同的对象可以具有相同的属性,但在使用==或===进行比较时,它们不被认为是相等的。这是因为它们是通过引用(内存中的位置)进行比较的,而不是按值进行比较的原始值。
为了测试两个对象在结构上是否相等,需要一个辅助函数。它将遍历每个对象的自身属性,以测试它们是否具有相同的值,包括嵌套对象。 可选地,对象的原型也可以通过传递true作为第三个参数来测试等价性。
function isDeepEqual(obj1,obj2, testPrototypes = false) {
// 如果两者类型不同,直接返回false
if (Object.prototype.toString.call(obj1) !== Object.prototype.toString.call(obj2)) {
return false
}
// 如果两者的值和类型都相等,直接返回true
if (obj1 === obj2) {
return true
}
// 如果两者都是函数则判断其转化为字符串后的值是否相等
if (typeof obj1 === 'function' && typeof obj2 === 'function') {
return obj.toString() === obj2.toString()
}
// 如果两者都是时间类型,则判断其毫秒值是否相等
if (obj1 instanceof Date && obj1 instanceof Date) {
return obj1.getTime() === obj2.getTime()
}
// 在其他情况下如果两者有一个不是对象则返回false(此时两者类型相同,判断一个就行)
if (typeof obj1 !== 'object') {
return false
}
const prototypesAreEqual = testPrototypes ?
isDeepEqual(
Object.getPrototypeOf(obj1), Object.getPrototypeOf(obj2), true
)
: true
// 其他对象(数组等)
const obj1Props = Object.getOwnProperties(obj1)
const obj2Props = Object.getOwnProperties(obj2)
return (
// 判断其属性长度是否相等
obj1Props.length === obj2Props.length &&
prototypesAreEqual &&
// 如果其属性也是对象,递归调用自身继续判断他们对应属性是否相等
obj1Props.every(prop => isDeepEqual(obj1[prop], obj2[prop]))
)
}
注意:理论上此方法可以任意数据结构,但是建议用于测试普通对象、数组、函数、日期。
评论