Auf diese Frage gibt es bereits mehr als 30 Antworten. Ich werde sie zusammenfassen und erklären (mit einer Analogie zu "meinem Vater") und meinen Lösungsvorschlag hinzufügen.
Sie haben 4+1 Klassen von Lösungen :
1) Verwenden Sie einen hakeligen, unvollständigen, schnellen Einzeiler
Gut, wenn man es eilig hat und 99 % Korrektheit funktioniert.
Beispiele hierfür sind, JSON.stringify()
vorgeschlagen von Pratik Bhalodiya , oder JSON.encode
von Joel Anair , oder .toString()
oder andere Methoden, die Ihre Objekte in einen String umwandeln und dann die beiden Strings mit ===
Zeichen für Zeichen.
Der Nachteil ist jedoch, dass es keine weltweit einheitliche Darstellung eines Objekts in String gibt. z.B. { a: 5, b: 8}
y {b: 8 and a: 5 }
gleich sind.
- Vorteile: Schnell, schnell.
- Nachteile: Hoffentlich funktioniert! Es wird nicht funktionieren, wenn die Umgebung/Browser/Engine die Reihenfolge der Objekte speichert (z.B. Chrome/V8) und die Reihenfolge der Schlüssel unterschiedlich ist (Dank an Eksapsy .) Also, überhaupt nicht garantiert. Die Leistung wäre auch bei großen Objekten nicht besonders gut.
Mein Vater Analogie
Wenn ich über meinen Vater spreche, " mein großer, gut aussehender Vater " und " mein gut aussehender großer Vater " sind ein und dieselbe Person! Aber die beiden Strings sind nicht identisch.
Beachten Sie, dass es tatsächlich eine korrekte (Standardweg) Bestellung der Adjektive in der englischen Grammatik, die sagt es sollte ein "gutaussehender großer Mann" sein, aber Sie riskieren Ihre Kompetenz, wenn Sie blind davon ausgehen, dass die Javascript-Engine von iOS 8 Safari auch die gleiche Grammatik befolgt, blind! #WelcomeToJavascriptNonStandards
2) Schreibe deine eigene rekursive Funktion
Gut, wenn Sie noch lernen.
Beispiele sind atmin's Lösung .
Der größte Nachteil besteht darin, dass man definitiv einige Randfälle übersehen wird. Haben Sie eine Selbstreferenz in Objektwerten? Haben Sie bedacht NaN
? Haben Sie zwei Objekte betrachtet, die dieselbe ownProperties
aber verschiedene prototypische Eltern?
Ich würde die Leute nur dazu ermutigen, dies zu tun, wenn sie üben und der Code nicht in die Produktion gehen soll. Das ist der einzige Fall, der das Rad neu erfinden hat seine Berechtigung.
- Vorteile: Gelegenheit zum Lernen.
- Nachteile: Nicht zuverlässig. Zeitaufwendig und bedenklich.
Mein Vater Analogie
Wenn mein Vater "John Smith" heißt und am "1.1.1970" Geburtstag hat, ist jeder, der "John Smith" heißt und am "1.1.1970" geboren ist, mein Vater.
Das ist normalerweise der Fall, aber was ist, wenn es zwei "John Smiths" gibt, die an diesem Tag geboren wurden? Wenn Sie die Größe der beiden berücksichtigen, erhöht das zwar die Genauigkeit, ist aber immer noch kein perfekter Vergleich.
2.1 Ihr begrenzter Umfang DIY-Vergleicher
Anstatt alle Eigenschaften rekursiv zu prüfen, könnte man in Erwägung ziehen, nur eine "begrenzte" Anzahl von Eigenschaften zu prüfen. Zum Beispiel, wenn die Objekte User
s, können Sie deren emailAddress
Feld.
Sie ist zwar immer noch nicht perfekt, aber die Vorteile gegenüber Lösung Nr. 2 liegen auf der Hand:
- Es ist vorhersehbar, und die Wahrscheinlichkeit eines Absturzes ist geringer.
- Sie steuern die "Definition" der Gleichheit, anstatt sich auf eine wilde Form und Gestalt des Objekts und dessen Prototyp und verschachtelte Eigenschaften zu verlassen.
3) Verwenden Sie eine Bibliotheksversion von equal
機能
Gut, wenn Sie eine Qualität auf Produktionsniveau benötigen und Sie das Design des Systems nicht ändern können.
Beispiele sind _.equal
von lodash , bereits in coolaj86's Antwort oder die von Angular oder Ember, wie sie in Tony Harveys Antwort oder Node's von Rafael Xavier .
- Vorteile: Das tun alle anderen auch.
- Nachteile: Externe Abhängigkeit, die zusätzliche Kosten für Arbeitsspeicher, CPU und Sicherheit verursachen kann, wenn auch nur in geringem Maße. Außerdem können immer noch einige Randfälle übersehen werden (z.B. ob zwei Objekte mit demselben
ownProperties
aber verschiedene prototypische Eltern sollten als gleich angesehen werden oder nicht). Zum Schluss, vous könnte ungewollt ein zugrundeliegendes Design-Problem damit beheben; ich sage es nur!
Mein Vater Analogie
Das ist so, als würde ich eine Agentur dafür bezahlen, meinen biologischen Vater anhand seiner Telefonnummer, seines Namens, seiner Adresse usw. ausfindig zu machen.
Es wird mehr kosten, und es ist wahrscheinlich genauer, als wenn ich den Background Check selbst durchführe, aber es deckt keine Sonderfälle ab, z.B. wenn mein Vater Einwanderer/Asylant ist und sein Geburtstag unbekannt ist!
4) Verwenden Sie einen IDentifier im Objekt
Gut, wenn Sie das Design des Systems (Objekte, mit denen Sie arbeiten) [noch] ändern können und Sie wollen, dass Ihr Code lange hält.
Sie ist nicht in allen Fällen anwendbar und möglicherweise nicht sehr leistungsfähig. Es ist jedoch eine sehr zuverlässige Lösung, wenn man es schaffen kann.
Die Lösung ist, dass jeder object
im System haben einen einzigartig Identifikator zusammen mit allen anderen Eigenschaften. Die Einzigartigkeit des Identifikators wird zum Zeitpunkt der Generierung garantiert. Und Sie werden diese ID (auch bekannt als UUID/GUID -- Global/universell eindeutiger Identifikator ), wenn es um den Vergleich zweier Objekte geht, d.h. sie sind gleich, wenn diese IDs gleich sind.
Die IDs können einfach sein auto_incremental
Zahlen, oder eine Zeichenkette, die über eine Bibliothek (empfohlen) oder ein Stück Code . Alles, was Sie tun müssen, ist sicherzustellen, dass es immer eindeutig ist, was im Falle von auto_incremental
kann eingebaut werden, oder im Fall von UUID können alle vorhandenen Werte geprüft werden (z.B. MySQL's UNIQUE
Spaltenattribut) oder einfach (wenn sie aus einer Bibliothek stammen) auf die extrem niedrige Wahrscheinlichkeit einer Kollision verlassen werden.
Beachten Sie, dass Sie die ID immer zusammen mit dem Objekt speichern müssen (um ihre Einzigartigkeit zu gewährleisten), und dass die Berechnung in Echtzeit möglicherweise nicht der beste Ansatz ist.
- Vorteile: Zuverlässig, effizient, nicht schmutzig, modern.
- Nachteile: Braucht zusätzlichen Platz. Möglicherweise muss das System umgestaltet werden.
Mein Vater Analogie
Es ist, als wüsste man, dass die Sozialversicherungsnummer meines Vaters 911-345-9283 lautet, so dass jeder, der diese SSN hat, mein Vater ist, und jeder, der behauptet, mein Vater zu sein, diese SSN haben muss.
Schlussfolgerung
Ich persönlich bevorzuge die Lösung Nr. 4 (ID), weil sie genauer und zuverlässiger ist als alle anderen. Wenn das nicht möglich ist, würde ich für die Vorhersagbarkeit die Lösung 2.1 und dann die Lösung 3 wählen. Wenn beides nicht möglich ist, dann #2 und schließlich #1.
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