在JavaScript中比较对象的最佳方法是什么?
例子:
var user1 = {name : "nerd", org: "dev"};
var user2 = {name : "nerd", org: "dev"};
var eq = user1 == user2;
alert(eq); // gives false
我知道如果两个对象引用完全相同的对象,那么它们是相等的,但是有没有方法检查它们是否具有相同的属性值?
以下方式对我有效,但这是唯一的可能性吗?
var eq = Object.toJSON(user1) == Object.toJSON(user2);
alert(eq); // gives true
我修改了上面的代码。对于我0!==false和null!==未定义。如果不需要这样严格的检查,请在代码中删除一个“=”sign-in“this[p]!==x[p]”。
Object.prototype.equals = function(x){
for (var p in this) {
if(typeof(this[p]) !== typeof(x[p])) return false;
if((this[p]===null) !== (x[p]===null)) return false;
switch (typeof(this[p])) {
case 'undefined':
if (typeof(x[p]) != 'undefined') return false;
break;
case 'object':
if(this[p]!==null && x[p]!==null && (this[p].constructor.toString() !== x[p].constructor.toString() || !this[p].equals(x[p]))) return false;
break;
case 'function':
if (p != 'equals' && this[p].toString() != x[p].toString()) return false;
break;
default:
if (this[p] !== x[p]) return false;
}
}
return true;
}
然后我用下一个对象测试了它:
var a = {a: 'text', b:[0,1]};
var b = {a: 'text', b:[0,1]};
var c = {a: 'text', b: 0};
var d = {a: 'text', b: false};
var e = {a: 'text', b:[1,0]};
var f = {a: 'text', b:[1,0], f: function(){ this.f = this.b; }};
var g = {a: 'text', b:[1,0], f: function(){ this.f = this.b; }};
var h = {a: 'text', b:[1,0], f: function(){ this.a = this.b; }};
var i = {
a: 'text',
c: {
b: [1, 0],
f: function(){
this.a = this.b;
}
}
};
var j = {
a: 'text',
c: {
b: [1, 0],
f: function(){
this.a = this.b;
}
}
};
var k = {a: 'text', b: null};
var l = {a: 'text', b: undefined};
a==b预期为真;返回true
a==c预期为假;返回false
c==d预期为假;返回false
a==e预期为假;返回false
f==g预期为真;返回true
h==g预期为假;返回false
i==j预期为真;返回true
d==k预期为假;返回false
k==l预期为假;返回false
当然不是唯一的方法——您可以原型化一个方法(在这里针对Object,但我当然不建议将Object用于实时代码)来复制C#/Java风格的比较方法。
编辑,因为似乎需要一个通用示例:
Object.prototype.equals = function(x)
{
for(p in this)
{
switch(typeof(this[p]))
{
case 'object':
if (!this[p].equals(x[p])) { return false }; break;
case 'function':
if (typeof(x[p])=='undefined' || (p != 'equals' && this[p].toString() != x[p].toString())) { return false; }; break;
default:
if (this[p] != x[p]) { return false; }
}
}
for(p in x)
{
if(typeof(this[p])=='undefined') {return false;}
}
return true;
}
请注意,使用toString()测试方法绝对不够好,但一个可以接受的方法非常困难,因为空格是否有意义,更不用说同义词方法和使用不同实现产生相同结果的方法。以及针对Object的原型设计问题。
我修改了上面的代码。对于我0!==false和null!==未定义。如果不需要这样严格的检查,请在代码中删除一个“=”sign-in“this[p]!==x[p]”。
Object.prototype.equals = function(x){
for (var p in this) {
if(typeof(this[p]) !== typeof(x[p])) return false;
if((this[p]===null) !== (x[p]===null)) return false;
switch (typeof(this[p])) {
case 'undefined':
if (typeof(x[p]) != 'undefined') return false;
break;
case 'object':
if(this[p]!==null && x[p]!==null && (this[p].constructor.toString() !== x[p].constructor.toString() || !this[p].equals(x[p]))) return false;
break;
case 'function':
if (p != 'equals' && this[p].toString() != x[p].toString()) return false;
break;
default:
if (this[p] !== x[p]) return false;
}
}
return true;
}
然后我用下一个对象测试了它:
var a = {a: 'text', b:[0,1]};
var b = {a: 'text', b:[0,1]};
var c = {a: 'text', b: 0};
var d = {a: 'text', b: false};
var e = {a: 'text', b:[1,0]};
var f = {a: 'text', b:[1,0], f: function(){ this.f = this.b; }};
var g = {a: 'text', b:[1,0], f: function(){ this.f = this.b; }};
var h = {a: 'text', b:[1,0], f: function(){ this.a = this.b; }};
var i = {
a: 'text',
c: {
b: [1, 0],
f: function(){
this.a = this.b;
}
}
};
var j = {
a: 'text',
c: {
b: [1, 0],
f: function(){
this.a = this.b;
}
}
};
var k = {a: 'text', b: null};
var l = {a: 'text', b: undefined};
a==b预期为真;返回true
a==c预期为假;返回false
c==d预期为假;返回false
a==e预期为假;返回false
f==g预期为真;返回true
h==g预期为假;返回false
i==j预期为真;返回true
d==k预期为假;返回false
k==l预期为假;返回false