1020 Stimmen

Wie bestimmt man die Gleichheit zweier JavaScript-Objekte?

Ein strikter Gleichheitsoperator sagt Ihnen, ob zwei Objekte Typen gleich sind. Gibt es jedoch eine Möglichkeit zu erkennen, ob zwei Objekte gleich sind, ähnlich wie der Hash-Code Wert in Java?

Stack Overflow Frage Gibt es irgendeine Art von HashCode-Funktion in JavaScript? ist dieser Frage ähnlich, erfordert aber eine eher akademische Antwort. Das obige Szenario zeigt, warum es notwendig wäre, eine zu haben, und ich frage mich, ob es irgendeine gleichwertige Lösung .

5 Stimmen

Gehen Sie auch dieser Frage nach stackoverflow.com/q/1068834/1671639

56 Stimmen

Beachten Sie, dass auch in Java, a.hashCode() == b.hashCode() tut no bedeuten, dass a ist gleich b . 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?"

3voto

Sir_baaron Punkte 325

Ich stand vor demselben Problem und beschloss, meine eigene Lösung zu schreiben. Da ich aber auch Arrays mit Objekten und umgekehrt vergleichen möchte, habe ich eine generische Lösung entwickelt. Ich beschloss, die Funktionen zum Prototyp hinzuzufügen, aber man kann sie leicht in eigenständige Funktionen umschreiben. Hier ist der Code:

Array.prototype.equals = Object.prototype.equals = function(b) {
    var ar = JSON.parse(JSON.stringify(b));
    var err = false;
    for(var key in this) {
        if(this.hasOwnProperty(key)) {
            var found = ar.find(this[key]);
            if(found > -1) {
                if(Object.prototype.toString.call(ar) === "[object Object]") {
                    delete ar[Object.keys(ar)[found]];
                }
                else {
                    ar.splice(found, 1);
                }
            }
            else {
                err = true;
                break;
            }
        }
    };
    if(Object.keys(ar).length > 0 || err) {
        return false;
    }
    return true;
}

Array.prototype.find = Object.prototype.find = function(v) {
    var f = -1;
    for(var i in this) {
        if(this.hasOwnProperty(i)) {
            if(Object.prototype.toString.call(this[i]) === "[object Array]" || Object.prototype.toString.call(this[i]) === "[object Object]") {
                if(this[i].equals(v)) {
                    f = (typeof(i) == "number") ? i : Object.keys(this).indexOf(i);
                }
            }
            else if(this[i] === v) {
                f = (typeof(i) == "number") ? i : Object.keys(this).indexOf(i);
            }
        }
    }
    return f;
}

Dieser Algorithmus besteht aus zwei Teilen: der Gleichheitsfunktion selbst und einer Funktion zum Auffinden des numerischen Index einer Eigenschaft in einem Array/Objekt. Die find-Funktion wird nur benötigt, weil indexof nur Zahlen und Strings und keine Objekte findet.

Man kann es auch so nennen:

({a: 1, b: "h"}).equals({a: 1, b: "h"});

Die Funktion gibt entweder true oder false zurück, in diesem Fall true. Der Algorithmus ermöglicht auch den Vergleich zwischen sehr komplexen Objekten:

({a: 1, b: "hello", c: ["w", "o", "r", "l", "d", {answer1: "should be", answer2: true}]}).equals({b: "hello", a: 1, c: ["w", "d", "o", "r", {answer1: "should be", answer2: true}, "l"]})

Das obere Beispiel gibt true zurück, auch wenn die Eigenschaften eine andere Reihenfolge haben. Ein kleines Detail, auf das Sie achten sollten: Dieser Code prüft auch, ob zwei Variablen den gleichen Typ haben, also ist "3" nicht dasselbe wie 3.

3voto

xameeramir Punkte 25274

Vorausgesetzt, dass die Reihenfolge der Eigenschaften im Objekt nicht geändert wird.

JSON.stringify() funktioniert sowohl für tiefe als auch für nicht-tiefe Objekttypen, wobei die Leistungsaspekte nicht ganz klar sind:

var object1 = {
  key: "value"
};

var object2 = {
  key: "value"
};

var object3 = {
  key: "no value"
};

console.log('object1 and object2 are equal: ', JSON.stringify(object1) === JSON.stringify(object2));

console.log('object2 and object3 are equal: ', JSON.stringify(object2) === JSON.stringify(object3));

1 Stimmen

Dies entspricht nicht den Wünschen des Auftraggebers, da es nur dann zu einer Übereinstimmung kommt, wenn beide Objekte die gleichen Schlüssel haben, was nicht der Fall ist. Es würde auch erfordern, dass die Schlüssel in der gleichen Reihenfolge sein, die auch nicht wirklich sinnvoll ist.

3 Stimmen

Was ist, wenn die Eigenschaften in unterschiedlicher Reihenfolge sind? Nein, das ist keine gute Methode

2voto

Bernard Igiri Punkte 1272

Ich würde von Hashing oder Serialisierung abraten (wie es die JSON-Lösung vorschlägt). Wenn Sie testen müssen, ob zwei Objekte gleich sind, dann müssen Sie definieren, was gleich bedeutet. Es könnte sein, dass alle Datenelemente in beiden Objekten übereinstimmen, oder es könnte sein, dass die Speicherorte übereinstimmen müssen (was bedeutet, dass beide Variablen auf das gleiche Objekt im Speicher verweisen), oder es könnte sein, dass nur ein Datenelement in jedem Objekt übereinstimmen muss.

Vor kurzem habe ich ein Objekt entwickelt, dessen Konstruktor jedes Mal, wenn eine Instanz erstellt wird, eine neue ID (beginnend mit 1 und um 1 erhöht) erzeugt. Dieses Objekt hat eine isEqual-Funktion, die diesen id-Wert mit dem id-Wert eines anderen Objekts vergleicht und true zurückgibt, wenn sie übereinstimmen.

In diesem Fall habe ich "gleich" so definiert, dass die ID-Werte übereinstimmen. Da jede Instanz eine eindeutige ID hat, könnte dies verwendet werden, um die Idee durchzusetzen, dass übereinstimmende Objekte auch denselben Speicherplatz belegen. Das ist allerdings nicht notwendig.

2voto

Oliver Dixon Punkte 6507

Ich sehe Spaghetti-Code-Antworten. Ohne die Verwendung von Drittanbieter-Libs, ist dies sehr einfach.

Sortieren Sie zunächst die beiden Objekte nach ihren Schlüsselnamen.

let objectOne = { hey, you }
let objectTwo = { you, hey }

// If you really wanted you could make this recursive for deep sort.
const sortObjectByKeyname = (objectToSort) => {
    return Object.keys(objectToSort).sort().reduce((r, k) => (r[k] = objectToSort[k], r), {});
}

let objectOne = sortObjectByKeyname(objectOne)
let objectTwo = sortObjectByKeyname(objectTwo)

Verwenden Sie dann einfach eine Zeichenkette, um sie zu vergleichen.

JSON.stringify(objectOne) === JSON.stringify(objectTwo)

1 Stimmen

Dies funktioniert auch nicht für Deep Copy, es hat nur eine Iterationstiefe.

0 Stimmen

Ich denke, @andras meint, dass Sie die Schlüssel von verschachtelten Objekten rekursiv sortieren müssen.

0 Stimmen

@eksapsy unterschiedliche Probleme haben unterschiedliche Lösungen. Lesbarkeit übertrumpft bei der Programmierung immer die Leistung, obwohl wir heute auf modernen Systemen den Speicher schonen können, Optimierungen sind die Wurzel des Übels bei der Programmierung. Ich bin sicher, wenn Sie "riesige" Objekte haben, dann ist die gesamte Architektur wahrscheinlich falsch; Sie sollten dann etwas wie Elastic für große JSON-Sammlungen in Betracht ziehen. Es gibt viele verschiedene Lösungen für dieses Problem, ich bin sicher, es könnte besser sein, ich habe das vor Jahren in aller Eile geschrieben.

2voto

iamabs2001 Punkte 107
let std1 = {
  name: "Abhijeet",
  roll: 1
}

let std2 = {
  name: "Siddharth",
  roll: 2
}

console.log(JSON.stringify(std1) === JSON.stringify(std2))

4 Stimmen

JSON.stringify({y: 1, x: 1}) !== JSON.stringify({x: 1, y: 1})

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X