Dies ist meine Version. Sie verwendet neue Objekt.Schlüssel Funktion, die in ES5 eingeführt wird, und Ideen/Tests aus + , + y + :
function objectEquals(x, y) {
'use strict';
if (x === null || x === undefined || y === null || y === undefined) { return x === y; }
// after this just checking type of one would be enough
if (x.constructor !== y.constructor) { return false; }
// if they are functions, they should exactly refer to same one (because of closures)
if (x instanceof Function) { return x === y; }
// if they are regexps, they should exactly refer to same one (it is hard to better equality check on current ES)
if (x instanceof RegExp) { return x === y; }
if (x === y || x.valueOf() === y.valueOf()) { return true; }
if (Array.isArray(x) && x.length !== y.length) { return false; }
// if they are dates, they must had equal valueOf
if (x instanceof Date) { return false; }
// if they are strictly equal, they both need to be object at least
if (!(x instanceof Object)) { return false; }
if (!(y instanceof Object)) { return false; }
// recursive object equality check
var p = Object.keys(x);
return Object.keys(y).every(function (i) { return p.indexOf(i) !== -1; }) &&
p.every(function (i) { return objectEquals(x[i], y[i]); });
}
///////////////////////////////////////////////////////////////
/// 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(null,null));
assert.isFalse(objectEquals(null,undefined));
assert.isFalse(objectEquals(/abc/, /abc/));
assert.isFalse(objectEquals(/abc/, /123/));
var r = /abc/;
assert.isTrue(objectEquals(r, r));
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}}));
Object.prototype.equals = function (obj) { return objectEquals(this, obj); };
var assertFalse = assert.isFalse,
assertTrue = assert.isTrue;
assertFalse({}.equals(null));
assertFalse({}.equals(undefined));
assertTrue("hi".equals("hi"));
assertTrue(new Number(5).equals(5));
assertFalse(new Number(5).equals(10));
assertFalse(new Number(1).equals("1"));
assertTrue([].equals([]));
assertTrue([1,2].equals([1,2]));
assertFalse([1,2].equals([2,1]));
assertFalse([1,2].equals([1,2,3]));
assertTrue(new Date("2011-03-31").equals(new Date("2011-03-31")));
assertFalse(new Date("2011-03-31").equals(new Date("1970-01-01")));
assertTrue({}.equals({}));
assertTrue({a:1,b:2}.equals({a:1,b:2}));
assertTrue({a:1,b:2}.equals({b:2,a:1}));
assertFalse({a:1,b:2}.equals({a:1,b:3}));
assertTrue({1:{name:"mhc",age:28}, 2:{name:"arb",age:26}}.equals({1:{name:"mhc",age:28}, 2:{name:"arb",age:26}}));
assertFalse({1:{name:"mhc",age:28}, 2:{name:"arb",age:26}}.equals({1:{name:"mhc",age:28}, 2:{name:"arb",age:27}}));
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 i = {
a: 'text',
c: {
b: [1, 0]
}
};
var j = {
a: 'text',
c: {
b: [1, 0]
}
};
var k = {a: 'text', b: null};
var l = {a: 'text', b: undefined};
assertTrue(a.equals(b));
assertFalse(a.equals(c));
assertFalse(c.equals(d));
assertFalse(a.equals(e));
assertTrue(i.equals(j));
assertFalse(d.equals(k));
assertFalse(k.equals(l));
// from comments on stackoverflow post
assert.isFalse(objectEquals([1, 2, undefined], [1, 2]));
assert.isFalse(objectEquals([1, 2, 3], { 0: 1, 1: 2, 2: 3 }));
assert.isFalse(objectEquals(new Date(1234), 1234));
// no two different function is equal really, they capture their context variables
// so even if they have same toString(), they won't have same functionality
var func = function (x) { return true; };
var func2 = function (x) { return true; };
assert.isTrue(objectEquals(func, func));
assert.isFalse(objectEquals(func, func2));
assert.isTrue(objectEquals({ a: { b: func } }, { a: { b: func } }));
assert.isFalse(objectEquals({ a: { b: func } }, { a: { b: func2 } }));
5 Stimmen
Gehen Sie auch dieser Frage nach stackoverflow.com/q/1068834/1671639
55 Stimmen
Beachten Sie, dass auch in Java,
a.hashCode() == b.hashCode()
tut no bedeuten, dassa
ist gleichb
. Das ist eine notwendige, aber keine hinreichende Bedingung.7 Stimmen
Wenn Sie Objekte in Ihrem Code vergleichen MÜSSEN, dann haben Sie Ihren Code wahrscheinlich falsch geschrieben. Die bessere Frage könnte lauten: "Wie kann ich diesen Code so schreiben, dass ich keine Objekte vergleichen muss?"
0 Stimmen
Versuchen Sie objekt-gleich Paket.
13 Stimmen
@th317erd kannst du dich bitte erklären?...
3 Stimmen
@ElMac Ich kann nicht direkt für die Person sprechen, aber ich stimme mit der Aussage überein und mein Gedankengang ist, dass JS-Objekte sehr oft ziemlich groß sind. Sie haben selten etwas mit sehr wenigen Eigenschaften wie
person = { name: "fred", age: 42 }
. Wenn Sie das tun und nach der exakten Gleichheit suchen müssen, scheint das eine Verschwendung zu sein. Meistens haben Ihre einfachen Objekte immer noch eine Menge Eigenschaften - und eine davon ist entweder einzigartig oder Sie wollen, dass eine davon eindeutig ist, z.B. eine Art ID. Dann kann man danach suchen und braucht nicht zu prüfen, ob jedes einzelne Objekt übereinstimmt.0 Stimmen
Die meisten der Kommentatoren hier haben Recht, dass dies keine sehr gute Methode ist. Seit diesem Beitrag habe ich viel mit dieser Methode herumgespielt, mit unterschiedlichem Erfolg. Letztlich ist es nicht eine sehr gute Methode für den Objektvergleich, und die Menge an zusätzlichem Code erforderlich, um es zu arbeiten meist richtig macht es nicht wert (verwenden Sie einfach eine einfache tiefe Objekt Komparator statt)
0 Stimmen
Versuchen Sie
deep-equal
NPM-Paket0 Stimmen
jsben.ch/1uLAP <= Leistungsvergleich zwischen JSON.stringify und fast-deep-equal
2 Stimmen
Die Stufe 2 Datensatz- und Tupelvorschlag wird dies drastisch vereinfachen:
#{ x: 5, y: 7 } === #{ x: 5, y: 7 }
,#[ 4, #{ a: "hello", b: "world" }, 6, 10 ] === #[ 4, #{ b: "world", a: "hello" }, 6, 10 ]
.0 Stimmen
Dies ist ein Konzept, das als oberflächlicher Gleichheitsvergleich bezeichnet wird. Es wird dieses Problem lösen stackoverflow.com/a/70815902/12872199
0 Stimmen
Ich gebe hier wirklich eine ähnlich nette Antwort: stackoverflow.com/a/71173966/1919821