严格相等运算符将告诉您两个对象类型是否相等。然而,是否有一种方法来判断两个对象是否相等,就像Java中的哈希码值一样?
堆栈溢出问题JavaScript中有hashCode函数吗?类似于这个问题,但需要一个更学术的答案。上面的场景说明了为什么有必要有一个,我想知道是否有等效的解决方案。
严格相等运算符将告诉您两个对象类型是否相等。然而,是否有一种方法来判断两个对象是否相等,就像Java中的哈希码值一样?
堆栈溢出问题JavaScript中有hashCode函数吗?类似于这个问题,但需要一个更学术的答案。上面的场景说明了为什么有必要有一个,我想知道是否有等效的解决方案。
当前回答
function isEqual(obj1, obj2){
type1 = typeof(obj1);
type2 = typeof(obj2);
if(type1===type2){
switch (type1){
case "object": return JSON.stringify(obj1)===JSON.stringify(obj2);
case "function": return eval(obj1).toString()===eval(obj2).toString();
default: return obj1==obj2;
}
}
return false;
}//have not tried but should work.
其他回答
最简单和逻辑的解决方案,比较一切像对象,数组,字符串,Int…
JSON。stringify({a: val1}) == JSON。stringify ({a: val2})
注意:
你需要用你的Object替换val1和val2 对于对象,必须对两侧对象进行递归排序(按键)
这是一个非常干净的CoffeeScript版本,你可以这样做:
Object::equals = (other) ->
typeOf = Object::toString
return false if typeOf.call(this) isnt typeOf.call(other)
return `this == other` unless typeOf.call(other) is '[object Object]' or
typeOf.call(other) is '[object Array]'
(return false unless this[key].equals other[key]) for key, value of this
(return false if typeof this[key] is 'undefined') for key of other
true
下面是测试:
describe "equals", ->
it "should consider two numbers to be equal", ->
assert 5.equals(5)
it "should consider two empty objects to be equal", ->
assert {}.equals({})
it "should consider two objects with one key to be equal", ->
assert {a: "banana"}.equals {a: "banana"}
it "should consider two objects with keys in different orders to be equal", ->
assert {a: "banana", kendall: "garrus"}.equals {kendall: "garrus", a: "banana"}
it "should consider two objects with nested objects to be equal", ->
assert {a: {fruit: "banana"}}.equals {a: {fruit: "banana"}}
it "should consider two objects with nested objects that are jumbled to be equal", ->
assert {a: {a: "banana", kendall: "garrus"}}.equals {a: {kendall: "garrus", a: "banana"}}
it "should consider two objects with arrays as values to be equal", ->
assert {a: ["apple", "banana"]}.equals {a: ["apple", "banana"]}
it "should not consider an object to be equal to null", ->
assert !({a: "banana"}.equals null)
it "should not consider two objects with different keys to be equal", ->
assert !({a: "banana"}.equals {})
it "should not consider two objects with different values to be equal", ->
assert !({a: "banana"}.equals {a: "grapefruit"})
EDIT: This method is quite flawed, and is rife with its own issues. I don't recommend it, and would appreciate some down-votes! It is problematic because 1) Some things can not be compared (i.e. functions) because they can not be serialized, 2) It isn't a very fast method of comparing, 3) It has ordering issues, 4) It can have collision issues/false positives if not properly implemented, 5) It can't check for "exactness" (===), and instead is based of value equality, which is oftentimes not what is desired in a comparison method.
这个问题的一个简单解决方案是对JSON字符串进行排序(每个字符),但很多人没有意识到这一点。这通常也比这里提到的其他解决方案更快:
function areEqual(obj1, obj2) {
var a = JSON.stringify(obj1), b = JSON.stringify(obj2);
if (!a) a = '';
if (!b) b = '';
return (a.split('').sort().join('') == b.split('').sort().join(''));
}
关于这个方法的另一个有用的事情是,您可以通过向JSON传递一个“replace”函数来筛选比较。stringify函数(https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify#Example_of_using_replacer_parameter)。下面只比较所有命名为“derp”的对象键:
function areEqual(obj1, obj2, filter) {
var a = JSON.stringify(obj1, filter), b = JSON.stringify(obj2, filter);
if (!a) a = '';
if (!b) b = '';
return (a.split('').sort().join('') == b.split('').sort().join(''));
}
var equal = areEqual(obj1, obj2, function(key, value) {
return (key === 'derp') ? value : undefined;
});
如果要比较JSON对象,可以使用https://github.com/mirek/node-rus-diff
npm install rus-diff
用法:
a = {foo:{bar:1}}
b = {foo:{bar:1}}
c = {foo:{bar:2}}
var rusDiff = require('rus-diff').rusDiff
console.log(rusDiff(a, b)) // -> false, meaning a and b are equal
console.log(rusDiff(a, c)) // -> { '$set': { 'foo.bar': 2 } }
如果两个对象不同,MongoDB兼容{$rename:{…},设置美元:{…},美元:{…返回}}like对象。
我需要模拟jQuery POST请求,因此对我来说重要的是两个对象具有相同的属性集(任何一个对象中都不缺少属性),并且每个属性值都是“相等的”(根据这个定义)。我不关心对象是否有不匹配的方法。
这是我将使用的,它应该足以满足我的特定要求:
function PostRequest() {
for (var i = 0; i < arguments.length; i += 2) {
this[arguments[i]] = arguments[i+1];
}
var compare = function(u, v) {
if (typeof(u) != typeof(v)) {
return false;
}
var allkeys = {};
for (var i in u) {
allkeys[i] = 1;
}
for (var i in v) {
allkeys[i] = 1;
}
for (var i in allkeys) {
if (u.hasOwnProperty(i) != v.hasOwnProperty(i)) {
if ((u.hasOwnProperty(i) && typeof(u[i]) == 'function') ||
(v.hasOwnProperty(i) && typeof(v[i]) == 'function')) {
continue;
} else {
return false;
}
}
if (typeof(u[i]) != typeof(v[i])) {
return false;
}
if (typeof(u[i]) == 'object') {
if (!compare(u[i], v[i])) {
return false;
}
} else {
if (u[i] !== v[i]) {
return false;
}
}
}
return true;
};
this.equals = function(o) {
return compare(this, o);
};
return this;
}
像这样使用:
foo = new PostRequest('text', 'hello', 'html', '<p>hello</p>');
foo.equals({ html: '<p>hello</p>', text: 'hello' });