由于在做键盘导航组件的项目时,有这样一个需求,当用户传入按键字母和网址的映射时,如果和 localStorage 中的不一样那么就用 localStorage 中存储的,这个时候就需要比较两个对象的内容是否相等,但是在 JS 中对象是一种引用类型.
obj1 = {
a: 1
}
obj2 = {
a: 1
}
console.log(obj1 === obj2) // false
即使两个对象的内容完全相同,因为它们的地址不同,因此 obj1 === obj2
会返回 fasle。
所以自己根据深拷贝时递归的思想写了一个比较两个对象之间内容是否相同的函数。
function compareObject (obj1, obj2) {
// 递归终止条件,当 obj1 或 obj2 不是对象时,此时就可以进行判断了
if (typeof obj1 !== 'object' || typeof obj2 !== 'object') {
if (obj1 === obj2) {
return true
} else if (obj1 !== obj2) {
return false
}
}
// 获取对象的自由属性组成的数组
const obj1PropsArr = Object.getOwnPropertyNames(obj1)
const obj2PropsArr = Object.getOwnPropertyNames(obj2)
// 如果数组的长度不相等,那么说明对象属性的个数都不同,返回 false
if (obj1PropsArr.length !== obj2PropsArr.length) {
return false
}
// 记录当前 compareObject 的返回值,默认是 true
let status = true
for (key of obj1PropsArr) {
status = compareObject(obj1[key], obj2[key])
// 关键代码,当 status 为 false 时下面就不用再进行判断了,说明两个对象的内容并不相同
// 如果没有下面这条语句,那么只要对象底层的内容是相同的那么就返回 true
if (!status) {
break
}
}
// 每次 compareObject 执行的返回结果
return status
}
测试代码:
// 判断两个对象的内容相等
const obj1 = {
a: 1,
b: {
c: 2,
d: {
e: 4
}
}
}
const obj2 = {
a: 1,
b: {
c: 2,
d: {
e: 4
}
}
}
console.log(compareObject(obj1, obj2)) // true
// 判断两个对象的内容不相等
const obj1 = {
a: 1,
b: {
c: 2,
d: {
e: 4
}
}
}
const obj2 = {
a: 1,
b: {
c: 2,
d: {
e: 5
}
}
}
console.log(compareObject(obj1, obj2)) // false
接下来再来强调一下 compareObject
函数中第 23 行这句关键代码,如果没有这条语句那么最后的返回结果只会取决于两个对象最底层属性(最后一次)的比较结果。
if (!status) {
break
}
例如,我将两个对象变为下面这样:
const obj1 = {
a: 1,
b: {
c: 3, // 和 obj2 不相等
d: {
e: 4
}
}
}
const obj2 = {
a: 1,
b: {
c: 2,
d: {
e: 4
}
}
}
console.log(compareObject(obj1, obj2)) // true
可以看到最后的返回结果是 true,因为最后的一次比较是 e 属性,它们的值是相等的。
上面这样的写法应该还有一些情况没有考虑到,对于我的项目需求而言已经足够了,如果哪位小伙伴发现了希望可以提出来,然后再将它改进一下,非常感谢。