Wie, um zu bestimmen, Gleichheit für zwei JavaScript-Objekte?
Einer strikten Gleichheits-operator wird Ihnen sagen, wenn zwei Objekt Arten gleich sind. Jedoch, gibt es eine Möglichkeit zu sagen, ob zwei Objekte gleich sind, viel wie der hash-code Wert in Java?
Stack Overflow Frage Gibt es irgendeine Art von hashCode-Funktion in JavaScript? ist ähnlich auf diese Frage, sondern erfordert eine mehr Akademische Antworten. Das Szenario oben zeigt, warum es notwendig wäre, eine zu haben, und ich Frage mich, ob es irgendwelche gleichwertige Lösung.
Schauen Sie auch in dieser Frage stackoverflow.com/q/1068834/1671639
Beachten Sie, dass, auch in Java,
Pls einen Blick in das qs:stackoverflow.com/questions/35933616/...
Wenn Sie vergleichen MÜSSEN, um Objekte in Ihrem code, als Sie wahrscheinlich schreiben Ihren code falsch. Die bessere Frage wäre: "Wie kann ich folgenden code schreiben, damit ich nicht haben, um einen Vergleich mit Objekten?"
können Sie bitte erklären, sich selbst?...
Beachten Sie, dass, auch in Java,
a.hashCode() == b.hashCode()
nicht implizieren, dass a
gleich b
. Es ist eine notwendige Bedingung, keine hinreichende.Pls einen Blick in das qs:stackoverflow.com/questions/35933616/...
Wenn Sie vergleichen MÜSSEN, um Objekte in Ihrem code, als Sie wahrscheinlich schreiben Ihren code falsch. Die bessere Frage wäre: "Wie kann ich folgenden code schreiben, damit ich nicht haben, um einen Vergleich mit Objekten?"
können Sie bitte erklären, sich selbst?...
InformationsquelleAutor | 2008-10-14
Du musst angemeldet sein, um einen Kommentar abzugeben.
Die kurze Antwort
Die einfache Antwort ist: Nein, es gibt keine generische Mittel zu bestimmen, dass ein Objekt gleich einem anderen in den Sinn, meinen Sie. Die Ausnahme ist, wenn Sie streng denken an ein Objekt typeless.
Die lange Antwort
Konzept ist, dass der Equals-Methode vergleicht zwei unterschiedliche Instanzen eines Objekts anzugeben, ob Sie gleich sind an Wert-Ebene. Allerdings ist es bis zu dem bestimmten Typ zu definieren, wie ein
Equals
Methode implementiert werden sollte. Ein iterativer Vergleich der Attribute mit primitiven Werten kann nicht genug sein, kann es durchaus sein, Attribute, die nicht als Teil des Objekts Wert. Zum Beispiel,In diesem oben genannten Fall, der
c
ist nicht wirklich wichtig, um zu bestimmen, ob zwei Instanzen von MyClass sind gleich, nura
undb
wichtig sind. In einigen Fällenc
variieren zwischen den Instanzen und noch nicht signifikant beim Vergleich.Hinweis: dieses Problem gilt, wenn Mitglieder können sich auch Instanzen von a geben und diese wäre all das benötigt, um ein Mittel zur Bestimmung der Geschlechter.
Weiter zu verkomplizieren, ist, dass in JavaScript die Unterscheidung zwischen Daten und Methode verwischt ist.
Ein Objekt-Referenz eine Methode, die aufgerufen wird, wenn ein event-handler, und dieser würde wahrscheinlich nicht als Teil des "value-Staat". In der Erwägung, dass ein anderes Objekt kann auch eine Funktion zugeordnet ist, führt eine wichtige Berechnungs-und dabei macht dieses Beispiel unterscheidet sich von anderen, einfach weil es verweist auf eine andere Funktion.
Was über ein Objekt, eine seiner bestehenden Prototypen Methoden überschrieben durch eine andere Funktion? Könnte es dann noch als gleich zu einem anderen Beispiel, dass es ansonsten identisch? Diese Frage kann nur beantwortet werden, in dem für jeden spezifischen Fall für jeden Typ.
Wie bereits erwähnt, die Ausnahme wäre ein streng typeless Objekt. In dem Fall die einzig sinnvolle Wahl ist ein iterativer und rekursiver Vergleich der einzelnen member. Auch dann ist zu Fragen, was ist der 'Wert' einer Funktion?
_.isEqual(obj1, obj2);
gut, wie diese Erklärung ist nicht zu geben, keine konkrete Lösung für das problem.
die Antwort konnte nicht geben keine Lösung, weil es keines gibt. Auch in Java, es gibt keine silberne Kugel auf Objekt-Gleichheit-Vergleich und richtig zu implementieren die
.equals
Methode ist nicht trivial, das ist, warum es ein solches Thema widmet sich in der Effektive Java.Herb, Was macht die beiden Objekte gleich ist sehr Anwendungs-spezifisch; nicht jede Eigenschaft eines Objekts sollte unbedingt berücksichtigt werden, so dass brute-forcing jede Eigenschaft eines Objekts ist nicht eine konkrete Lösung.
gegoogelt
javascript equality object
, bekam die tl;dr-Antwort, nahm one-liner von @chovy Kommentar. dankeInformationsquelleAutor AnthonyWJones
Warum das Rad neu erfinden? Geben Lodash versuchen. Es hat eine Reihe von must-have-Funktionen wie isEqual().
Es wird brute-force-prüfen Sie die einzelnen Schlüssel-Wert - genau wie die anderen Beispiele auf dieser Seite - mit ECMAScript 5 und native Optimierungen, wenn Sie im browser zur Verfügung.
Hinweis: bereits diese Antwort empfohlen Underscore.js, aber lodash getan hat, einen besseren job zu bekommen, bugs zu fixen und Adressierung Probleme mit der Konsistenz.
wenn man sich anschaut, was sonst Unterstrich Sie gibt, die Sie nicht bereuen zieht es in
Auch wenn Sie es sich leisten können nicht zu haben, Unterstrich als eine Abhängigkeit, ziehen Sie die isEqual-Funktion aus, erfüllen die Anforderungen der Lizenzen und bewegen auf. Es ist bei weitem die umfassende Gleichheit test erwähnt auf stackoverflow.
Es ist ein fork von Unterstrich namens LoDash und Autor ist sehr besorgt mit der Konsistenz Probleme wie, dass. Test mit LoDash und sehen, was Sie bekommen.
Sie können das standalone-Modul, wenn Sie nicht wollen, dass die gesamte Bibliothek npmjs.com/package/lodash.isequal
InformationsquelleAutor CoolAJ86
Den Standard-Gleichheits-operator in JavaScript Objekte ergibt true, wenn Sie sich auf der gleichen Position im Speicher.
Wenn Sie benötigen eine andere Gleichheits-operator müssen Sie eine
equals(other)
- Methode, oder etwas ähnliches, um Ihre Klassen und die Einzelheiten der problem domain wird bestimmen, was genau das bedeutet.Hier ist eine Spielkarte Beispiel:
Nicht immer. Konvertieren von Objekten in JSON und vergleichen von strings werden können, sehr rechenintensiv für komplexe Objekte in engen loops. Für einfache Objekte ist es wahrscheinlich egal, viel, aber in Wirklichkeit ist es wirklich hängt von Ihrer spezifischen situation. Eine richtige Lösung kann so einfach wie das vergleichen von Objekt-IDs oder die überprüfung jedes Haus, aber seine Korrektheit diktiert wird vollständig von der problem-Domäne.
Sollten wir nicht die Daten vergleichen geben?! zurück anderen.Rang === diese.rank && andere.Anzug === diese.Anzug;
wahrscheinlich nicht. Im JavaScript-Typen sind ziemlich schnell und Locker, aber wenn Sie in Ihrer domain-Typen wichtig sind, dann möchten Sie vielleicht zu prüfen, die Typen auch.
Andere problem mit der Konvertierung von JSON ist, dass die Reihenfolge der Eigenschaften in den string bedeutsam.
{x:1, y:2}
!=={y:2, x:1}
InformationsquelleAutor Daniel X Moore
Wenn Sie eine JSON-Bibliothek Kodieren Sie jedes Objekt als JSON -, dann vergleichen Sie die resultierenden strings auf Gleichheit.
HINWEIS: diese Antwort wird in vielen Fällen funktionieren, da mehrere Leute haben darauf hingewiesen, in den Kommentaren ist es problematisch, für eine Vielzahl von Gründen. In fast allen Fällen werden Sie wollen, finden Sie eine robustere Lösung.
Das ist eine gute Frage, und wirft eine weitere Frage, ob zwei Objekte mit gleichen Eigenschaften in verschiedenen Anordnungen sind wirklich gleich ist oder nicht. Hängt davon ab, was du damit meinst gleich, denke ich.
Beachten Sie, dass die meisten Encoder und stringifiers ignorieren, Funktionen und konvertieren von nonfinite zahlen, wie NaN, zu null.
Ich Stimme Guido, Reihenfolge der Eigenschaften sind wichtig, und es kann nicht garantiert werden. @JoelAnair, ich denke, dass zwei Objekte mit den gleichen Eigenschaften in verschiedene Aufträge sollten als gleich angesehen, wenn der Wert der Eigenschaften, die gleich sind.
Interessant scheint auf den ersten, aber, wie jeder darauf hingewiesen hat, es kann nicht wirklich vertrauenswürdig.
InformationsquelleAutor Joel Anair
Kurze funktionelle
deepEqual
Umsetzung:Bearbeiten: version 2, mit jib ' s Vorschlag und ES6 Pfeil-Funktionen:
reduce
mitevery
zu vereinfachen.href="https://jsfiddle.net/om81qz1h/" >jsfiddle.net/om81qz1h
Dieser schlägt fehl, wenn Sie vergleichen zwei Daten
deepEqual({}, []) gibt true zurück,
ja, wenn Sie die Pflege für solche Ecke Fall, hässliche Lösung ist zu ersetzen
: (x === y)
mit: (x === y && (x != null && y != null || x.constructor === y.constructor))
InformationsquelleAutor atmin
Wenn Sie ein deep-copy-Funktion nützlich, können Sie verwenden Sie die folgenden trick, um noch Verwendung
JSON.stringify
beim abgleichen auf die Reihenfolge der Eigenschaften:Demo: http://jsfiddle.net/CU3vb/3/
Begründung:
Da die Eigenschaften von
obj1
kopiert, um den Klon einer nach Ihrer Reihenfolge in der Klon erhalten wird. Und wenn die Eigenschaften vonobj2
kopiert, um den Klon, da Eigenschaften, die bereits inobj1
wird einfach überschrieben werden, Ihre Aufträge in den Klon erhalten.Zitate gebraucht hat 😉 ich erinnere mich, dieses zu testen in mehreren Browsern, immer konsistente Ergebnisse. Aber natürlich, niemand kann garantieren, das Verhalten übrigen das gleiche in zukünftigen Browser/Motoren. Dies ist ein trick (wie schon genannt die Antwort) am besten, und ich wusste nicht, dass es eine todsichere Methode zum vergleichen von Objekten.
Sicher, hier ist einige Hinweise: ECMAScript-Spezifikation sagt Objekt "ungeordnete"; und Antwort für den tatsächlichen abweichenden Verhalten auf die aktuellen Browser.
Vielen Dank dafür! Beachten Sie aber bitte, war ich nie behauptet die Erhaltung der Ordnung zwischen code und kompilierte Objekt. Ich war zu fordern die Erhaltung der Reihenfolge der Eigenschaften, deren Werte ersetzt zu bekommen. Das war der Schlüssel, mit meiner Lösung: verwenden Sie ein mixin zu einfach überschreiben Immobilien-Werte. Vorausgesetzt Implementierungen in der Regel entscheiden, ob Sie irgendeine Art von hashmap, ersetzen Sie einfach die Werte erhalten bleiben sollte die Reihenfolge der keys. Es ist in der Tat genau diese, die ich hatte getestet in verschiedenen Browsern.
ist es möglich, diese Einschränkung ein wenig mehr explicit (Fett,...). Die meisten Menschen tun einfach copy-paste ohne den text zu Lesen um ihn...
InformationsquelleAutor Ateş Göral
Sind Sie versuchen, um zu testen, ob zwei Objekte gleich? dh: Ihre Eigenschaften sind gleich?
Wenn dies der Fall ist, werden Sie wahrscheinlich bemerkt haben, diese situation:
haben Sie vielleicht etwas wie das hier tun:
Offensichtlich, dass die Funktion könnte tun, mit ein bisschen Optimierung, und die Fähigkeit zu tun, tief-Prüfung (zu Griff verschachtelte Objekte:
var a = { foo : { fu : "bar" } }
), aber Sie bekommen die Idee.Als FÜR hingewiesen, die Sie möglicherweise anpassen müssen, um diese für Ihre eigenen Zwecke, zB: verschiedene Klassen haben unterschiedliche Definitionen von "gleich". Wenn Sie gerade arbeiten mit einfachen Objekten, die über ausreichen kann, andernfalls wird eine benutzerdefinierte
MyClass.equals()
- Funktion kann der Weg zu gehen.InformationsquelleAutor nickf
Einfachste und logische Lösungen für den Vergleich alles Wie Object, Array, String, Int...
JSON.stringify({a: val1}) === JSON.stringify({a: val2})
Hinweis:
val1
undval2
mit Ihr ObjektJSON.stringify
hat eine alphabetische Neuordnung? (Ich kann nicht finden dokumentiert.)yup du hast Recht ... für das Objekt, haben Sie zu Sortieren rekursiv für beide Seiten Objekte
Dies gilt nicht für Objekte mit zirkulären Referenzen
InformationsquelleAutor Pratik Bhalodiya
In Node.js haben, können Sie seine native
require("assert").deepEqual
. Mehr info:http://nodejs.org/api/assert.html
Beispiel:
Ein weiteres Beispiel, das gibt
true
/false
anstatt Fehler:Chai
hat diese Funktion auch. In Ihrem Fall, verwenden Sie:var foo = { a: 1 }; var bar = { a: 1 }; expect(foo).to.deep.equal(bar); // true;
Einige Versionen von Node.js set
error.name
zu"AssertionError [ERR_ASSERTION]"
. In diesem Fall würde ich ersetzen Sie die if-Anweisung mitif (error.code === 'ERR_ASSERTION') {
.InformationsquelleAutor Rafael Xavier
Hier ist eine Lösung in ES6/ES2015 mit einem funktionalen Stil Ansatz:
demo verfügbar hier
InformationsquelleAutor Alan R. Soares
Ich weiß nicht, ob jemand etwas ähnliches gepostet, aber hier ist eine Funktion, die ich durchgeführt, um zu überprüfen für die Objekt-Gleichheit.
Außerdem macht es rekursiv, so kann es auch überprüfen, für Tiefe Gleichheit, wenn es das ist, was Sie es nennen.
es ist offensichtlich, dass die ordnungsgemäße Gleichheit checker muss rekursiv sein. Ich denke, eine solche rekursive Antworten die richtige Antwort. Die akzeptierte Antwort nicht geben code und es hilft nicht
InformationsquelleAutor Zac
können Sie
_.isEqual(obj1, obj2)
von der underscore.js Bibliothek.Hier ist ein Beispiel:
Finden Sie in der offiziellen Dokumentation von hier: http://underscorejs.org/#isEqual
InformationsquelleAutor Bentaiba Miled Basma
Eine einfache Lösung für dieses Problem, die viele Menschen nicht wissen, ist das Sortieren der JSON-strings (pro Charakter). Dies ist in der Regel auch schneller als die anderen Lösungen, die hier erwähnt werden:
Andere nützliche Sache über diese Methode können Sie einen filter für Vergleiche mit der übergabe eines "replacer" - Funktion, um die JSON.stringify Funktionen (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify#Example_of_using_replacer_parameter). Im folgenden wird nur vergleichen Sie alle Objekte, Schlüssel namens "derp":
areEqual({a: 'b'}, {b: 'a'})
bekommttrue
dann?Ja, ich merkte nach der Buchung, dass diese "Lösung" hat Probleme. Es braucht ein wenig mehr Arbeit in die Sortier-Algorithmus, um tatsächlich zu funktionieren.
InformationsquelleAutor th317erd
Wenn Sie ES6+ über Babel oder sonst, können Sie auch
Object.is(x, y)
.Referenz: http://wiki.ecmascript.org/doku.php?id=harmony:egal#object.is_x_y
babeljs.io/docs/Verwendung/polyfill
Object.is([], []);
Ergebnis: false Quelle:InformationsquelleAutor Daniel Li
Würd ich abraten hashing oder Serialisierung (JSON Lösung vorschlagen). Wenn Sie brauchen, um zu testen, ob zwei Objekte gleich sind, dann werden Sie brauchen, um zu definieren, was gleich bedeutet. Es könnte sein, dass alle Daten, die Mitglieder beider Objekte übereinstimmen, oder es könnte sein, dass müssen die Speicheradressen übereinstimmen (d.h. beide Variablen verweisen auf das gleiche Objekt im Speicher), oder kann sein, dass nur ein Daten-member in jedem Objekt müssen übereinstimmen.
Kürzlich entwickelte ich ein Objekt, dessen Konstruktor erstellt eine neue id (beginnend mit 1 und Erhöhung um 1) jedes mal, wenn eine Instanz erstellt wird. Dieses Objekt hat eine isEqual-Funktion vergleicht den id-Wert mit dem Wert der id eines anderen Objekts und gibt true zurück, wenn Sie übereinstimmen.
In diesem Fall habe ich definiert "gleich" im Sinne von das die id-Werte übereinstimmen. Da jede Instanz hat eine eindeutige id, diese könnte verwendet werden, um die Durchsetzung der Idee, dass passende Objekte auch belegen den gleichen Speicherbereich. Obwohl, dass ist nicht notwendig.
InformationsquelleAutor Bernard Igiri
Benötigen ein allgemeineres Objekt-Vergleich Funktion als gepostet wurden, habe ich gekocht bis die folgenden. Kritik erwünscht...
Seien Sie sehr vorsichtig über das ändern
Object.prototype
-- in den allermeisten Fällen ist es nicht ratsam (Ergänzungen erscheinen in allen for..in-Schleifen, zum Beispiel). VielleichtObject.equals = function(aObj, bObj) {...}
?InformationsquelleAutor Liam
Wenn Sie vergleichen JSON-Objekte, die Sie verwenden können, https://github.com/mirek/node-rus-diff
Verwendung:
Wenn zwei Objekte unterschiedlich sind, wird eine MongoDB-kompatible
{$rename:{...}, $unset:{...}, $set:{...}}
wie Objekt zurückgegeben.InformationsquelleAutor Mirek Rusin
Ich Stand vor dem gleichen problem und deccided zu schreiben, meine eigene Lösung. Aber da will ich auch vergleichen von Arrays mit Objekten und Umgekehrt, gestaltete ich eine generische Lösung. Ich beschloss, um die Funktionen hinzuzufügen, die auf den Prototyp, aber man kann einfach schreiben Sie Sie auf standalone-Funktionen. Hier ist der code:
Dieser Algorithmus ist in zwei Teile aufgeteilt; Die equals-Funktion und eine Funktion, die den numerischen index eines Grundstücks in ein array /Objekt. Die find-Funktion wird nur dann benötigt, weil indexof finds nur zahlen und strings und keine Objekte .
Kann man es nennen wie diese:
Die Funktion entweder true oder false zurückgibt, in diesem Fall wahr.
Der Algorithmus als ermöglicht den Vergleich zwischen sehr komplexe Objekte:
Oberen Beispiel wird true zurückgegeben, auch wenn die Eigenschaften haben eine andere Bestellung. Ein kleines detail achten: Dieser code überprüft auch für die gleiche Art von zwei Variablen, so "3" ist nicht das gleiche wie 3.
InformationsquelleAutor Sir_baaron
Wollte nur beitragen, meine version von Objekten-Vergleich unter Verwendung von ein paar es6-features. Es doesn ' T nehmen eine Bestellung zu berücksichtigen. Nach der Konvertierung werden alle if/else ist zu ternären ich habe kam mit folgenden:
InformationsquelleAutor Egor Litvinchuk
Ist es sinnvoll zu prüfen, zwei Objekte gleich, wenn Sie alle die gleichen Werte für alle Eigenschaften und rekursiv für alle verschachtelten Objekte und arrays. Ich halte auch die folgenden zwei Objekte gleich:
Ebenso können arrays haben den "fehlenden" Elemente und nicht definierten Elemente. Ich würde behandeln alle das selbe:
Eine Funktion, die diese definition der Gleichheit:
Source code (einschließlich der Helfer-Funktionen, generalType und uniqueArray):
Unit-Test und Test-Runner hier.
InformationsquelleAutor mckoss
Mache ich die folgenden Annahmen, die mit dieser Funktion:
Diese sollten behandelt werden, als eine demonstration von einer einfachen Strategie.
InformationsquelleAutor Aldo Fregoso
Dies ist eine Ergänzung für alle der oben genannten, nicht ein Ersatz. Wenn Sie brauchen, um schnell flach-vergleichen Sie Objekte, ohne zu überprüfen, zusätzliche rekursive Fälle. Hier ist ein Schuss.
Dieser vergleicht für Sie: 1) ist die Gleichheit der Anzahl der eigenen Eigenschaften, 2) die Gleichheit der Namen von Tasten, 3) wenn bCompareValues == true, wird die Gleichheit der entsprechenden property-Werte und deren Typen (triple Gleichheit)
InformationsquelleAutor Lex
Vergleichen-Tasten für einfache Schlüssel/Wert-Paare-Objekt-Instanzen, die ich benutze:
Einmal die Tasten sind im Vergleich, eine einfache zusätzliche
for..in
Schleife ist genug.Komplexität ist O(N*N) mit N ist die Anzahl der Tasten.
Ich hoffe/denke, Objekte definiere ich nicht halten mehr als 1000 Eigenschaften...
InformationsquelleAutor Hefeust CORTES
Ich weiß das ist ein bisschen alt, aber ich möchte eine Lösung, ich kam mit diesem problem.
Ich hatte ein Objekt, und ich wollte wissen, wenn sich seine Daten geändert haben. "etwas ähnliches Objekt.beobachten" und was ich Tat, war:
Diese hier dupliziert werden können, und erstellen Sie einen anderen Satz von arrays zu vergleichen, die Werte und Schlüssel.
Es ist sehr einfach, weil Sie werden nun arrays und gibt false zurück, wenn Objekte unterschiedliche Größen haben.
false
, da arrays nicht vergleichen, nach Wert, z.B.[1,2] != [1,2]
.InformationsquelleAutor inoabrian
Hier eine version des stringify trick, die weniger Tippen und funktioniert in vielen Fällen für trivial JSON-Daten Vergleiche.
InformationsquelleAutor EJW
Sehe ich spaghetti-code Antworten.
Ohne Verwendung jeglicher third-party-libs, das ist sehr einfach.
Erstens Sortieren Sie die beiden Objekte durch Schlüssel Ihren Schlüssel Namen.
Dann einfach mit einem string zu vergleichen.
Ich denke, @andras bedeutet, dass Sie brauchen, um rekursiv Sortieren Schlüssel von verschachtelten Objekten.
InformationsquelleAutor Oliver Dixon