由于对象是引用类型,即使内容一摸一样的两个对象,判断他们是否相等也是不等的,他们是存在不同地址中的相同内容,是不相等的;只有通过赋值,两个对象指向的是同一个地址,同一个内容,这样才相等。
那js中判断对象是否相等的方法有哪些呢?
- JSON.stringify()
首先,我们可以通过将对象通过JSON.stringify()方法将对象转换成字符串,然后再比较
局限性:
如果对象里属性的位置发生变化,转换来的字符串就不相等,但实际我们只需要看他们的内容是否一致,与顺序没有关系,所以这种方法有局限性。 - 通用方法:
function equals(x,y){
var f1=x instanceof Object;
var f2=y instanceof Object;
if(!f1 || !f2){
return x===y
}
if(Object.keys(x).length!== Object.keys(y).length){
return false
}
for(var p in x){
var a= x[p] instanceof Object;
var b= y[p] instanceof Object;
if(a && b){
equals(x[p],y[p])
}else if(x[p]!=y[p]){
return false;
}
}
return true;
}
console.log(equals({a:1,b:2},{a:1,b:{c:4}}))
首先判断是不是引用类型的,如果有一个不是,那就进行直接判断。
若全是引用类型的,那就先看一下属性值的长度是否相等,若不相等,就直接false啦。
若相等,就接着遍历里边的每一个属性,还是先看里边的属性是哪一个类型,如果全是引用类型,那就接着对里边的属性调用equals递归函数。如果不全是引用类型,那就比较这两个值是否相等,若不相等就直接false啦。
若遍历一圈下来都没有返回false,说明都相等啦。所以返回true。
注意,最好不要用forin循环,因为他会遍历原型链所有的可枚举属性,而
function equals(x,y){
var f1=x instanceof Object;
var f2=y instanceof Object;
if(!f1 || !f2){
return x===y
}
if(Object.keys(x).length!== Object.keys(y).length){
return false
}
Object.keys(x).forEach((p)=>{
var a= x[p] instanceof Object;
var b= y[p] instanceof Object;
console.log(y[p])
if(a && b){
equals(x[p],y[p])
}else if(x[p]!=y[p]){
return false;
}
})
return true;
}
但是forEach里的return不会终止循环,所以还是不用forEach了,
function equals(x, y) {
var f1 = x instanceof Object;
var f2 = y instanceof Object;
if (!f1 || !f2) {
return x === y
}
if (Object.keys(x).length !== Object.keys(y).length) {
return false
}
var newX = Object.keys(x);
for (var p in newX) {
p = newX[p];
var a = x[p] instanceof Object;
var b = y[p] instanceof Object;
if (a && b) {
equals(x[p], y[p])
} else if (x[p] != y[p]) {
return false;
}
}
return true;
}
console.log(equals({ a: 1, b: 2 }, { a: 1, d: 2 }))