严格相等运算符将告诉您两个对象类型是否相等。然而,是否有一种方法来判断两个对象是否相等,就像Java中的哈希码值一样?
堆栈溢出问题JavaScript中有hashCode函数吗?类似于这个问题,但需要一个更学术的答案。上面的场景说明了为什么有必要有一个,我想知道是否有等效的解决方案。
严格相等运算符将告诉您两个对象类型是否相等。然而,是否有一种方法来判断两个对象是否相等,就像Java中的哈希码值一样?
堆栈溢出问题JavaScript中有hashCode函数吗?类似于这个问题,但需要一个更学术的答案。上面的场景说明了为什么有必要有一个,我想知道是否有等效的解决方案。
当前回答
下面是一个使用JSON的简短实现。stringify但按@Jor建议的方式对键进行排序。
一些测试来自@EbrahimByagowi的回答。
当然,通过使用JSON。stringify,解决方案仅限于JSON序列化类型(字符串、数字、JSON对象、数组、布尔值、null)。不支持Date、Function等对象。
function objectEquals(obj1, obj2) { const JSONstringifyOrder = obj => { const keys = {}; JSON.stringify(obj, (key, value) => { keys[key] = null; return value; }); return JSON.stringify(obj, Object.keys(keys).sort()); }; return JSONstringifyOrder(obj1) === JSONstringifyOrder(obj2); } /////////////////////////////////////////////////////////////// /// The borrowed tests, run them by clicking "Run code snippet" /////////////////////////////////////////////////////////////// var printResult = function (x) { if (x) { document.write('<div style="color: green;">Passed</div>'); } else { document.write('<div style="color: red;">Failed</div>'); } }; var assert = { isTrue: function (x) { printResult(x); }, isFalse: function (x) { printResult(!x); } } assert.isTrue(objectEquals("hi","hi")); assert.isTrue(objectEquals(5,5)); assert.isFalse(objectEquals(5,10)); assert.isTrue(objectEquals([],[])); assert.isTrue(objectEquals([1,2],[1,2])); assert.isFalse(objectEquals([1,2],[2,1])); assert.isFalse(objectEquals([1,2],[1,2,3])); assert.isTrue(objectEquals({},{})); assert.isTrue(objectEquals({a:1,b:2},{a:1,b:2})); assert.isTrue(objectEquals({a:1,b:2},{b:2,a:1})); assert.isFalse(objectEquals({a:1,b:2},{a:1,b:3})); assert.isTrue(objectEquals({1:{name:"mhc",age:28}, 2:{name:"arb",age:26}},{1:{name:"mhc",age:28}, 2:{name:"arb",age:26}})); assert.isFalse(objectEquals({1:{name:"mhc",age:28}, 2:{name:"arb",age:26}},{1:{name:"mhc",age:28}, 2:{name:"arb",age:27}}));
其他回答
我不是Javascript专家,但这里有一个简单的解决方法。我检查三件事:
它是一个对象,而且它不是null,因为typeof null是对象。 如果两个对象的属性计数相同?否则它们就不相等。 遍历一个对象的属性,并检查对应的属性在第二个对象中是否具有相同的值。
function deepEqual (first, second) { // Not equal if either is not an object or is null. if (!isObject(first) || !isObject(second) ) return false; // If properties count is different if (keys(first).length != keys(second).length) return false; // Return false if any property value is different. for(prop in first){ if (first[prop] != second[prop]) return false; } return true; } // Checks if argument is an object and is not null function isObject(obj) { return (typeof obj === "object" && obj != null); } // returns arrays of object keys function keys (obj) { result = []; for(var key in obj){ result.push(key); } return result; } // Some test code obj1 = { name: 'Singh', age: 20 } obj2 = { age: 20, name: 'Singh' } obj3 = { name: 'Kaur', age: 19 } console.log(deepEqual(obj1, obj2)); console.log(deepEqual(obj1, obj3));
如果您有一个方便的深度复制函数,您可以使用下面的技巧来使用JSON。Stringify同时匹配属性的顺序:
function equals(obj1, obj2) {
function _equals(obj1, obj2) {
return JSON.stringify(obj1)
=== JSON.stringify($.extend(true, {}, obj1, obj2));
}
return _equals(obj1, obj2) && _equals(obj2, obj1);
}
演示:http://jsfiddle.net/CU3vb/3/
理由是:
由于obj1的属性被逐个复制到克隆中,因此它们在克隆中的顺序将被保留。当obj2的属性被复制到克隆对象时,因为obj1中已经存在的属性将被简单地覆盖,它们在克隆对象中的顺序将被保留。
我需要模拟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' });
let std1 = {
name: "Abhijeet",
roll: 1
}
let std2 = {
name: "Siddharth",
roll: 2
}
console.log(JSON.stringify(std1) === JSON.stringify(std2))
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.