2016-07-29 7 views
1

Ich benutze die lodash isEqual Funktion für einen tiefen Vergleich von JavaScript-Objekten. Es erfordert Objekte die gleichen Prototypen haben, wie gleich, wie die folgenden Sitzung mit dem Knoten REPL zeigt zählen:Js tiefe Gleichheit ohne Rücksicht auf Prototypen überprüfen (vorzugsweise in lodash)

> const isEqual = require('lodash').isEqual 
undefined 
> isEqual({a:3},{a:3}) 
true 
> class Foo { constructor(x) {this.a = x} } 
[Function: Foo] 
> isEqual(new Foo(3), new Foo(3)) 
true 
> isEqual({a:3}, new Foo(3)) 
false 

Gibt es eine einfache Art und Weise tief Vergleich ohne Berücksichtigung Prototypen zu tun? Es sollte immer noch einen speziellen Vergleich für Daten machen; Ich will nur, in den Fällen, wo lodash einen rekursiven Vergleich machen würde, dass es egal ist, ob sich Prototypen unterscheiden. Natürlich konnte ich es selbst programmieren, aber ich benutzte lodash, um so etwas nicht machen zu müssen. Ich dachte auch daran zu tun

isEqual(JSON.parse(JSON.stringify(obj1)), JSON.parse(JSON.stringify(obj2))) 

Vielleicht ist es in Ordnung, aber es scheint brutto.

+0

Sie nur verwenden können, 'JSON.stringify ({a: 3}) === JSON.stringify (new Foo (3)) 'im letzten Beispiel; – user3335966

+0

Das funktioniert nicht. Die meisten Browser geben unterschiedliche Ergebnisse für 'JSON.stringify ({a: 1, b: 2})' und 'JSON.stringify ({b: 2, a: 1})' '. – gmr

Antwort

0

Dies ist nicht "eine einfache Art und Weise", aber es kann helfen:

function eq(a, b){ 
    if(!_.isObject(a) || !_.isObject(b)) return 'Error! Only for objects.'; 
    var keysA = Object.keys(a).sort(); 
    var keysB = Object.keys(b).sort(); 
    if(!_.isEqual(keysA, keysB)) return false; 
    for(var i = 0, l = keysA.length; i < l; i++){ 
     if(
      (_.isObject(a[keysA[i]]) && _.isObject(b[keysB[i]]) && !eq(a[keysA[i]], b[keysB[i]])) || 
      (!_.isObject(a[keysA[i]]) && !_.isObject(b[keysB[i]]) && a[keysA[i]] !== b[keysB[i]]) || 
      (_.isObject(a[keysA[i]]) !== _.isObject(b[keysB[i]])) 
     ) return false; 
    } 
    return true; 
} 

eq({a: 1}, new Foo(1));   //true 
eq({a: 1}, new Foo(2));   //false 
eq({a: 1, b: 2}, {b: 2, a: 1}); //true 
eq({a: 1, b: 3}, {b: 2, a: 1}); //false 

eq({a: {a: 1}}, {a: new Foo(1)})//true 
+0

Danke. Es sieht für mich so aus, als ob diese Lösung auf Daten zurückgeht und vielleicht habe ich sie in anderen Fällen nicht berücksichtigt (oder auch nicht). Ich denke, wenn ich den Weg gehen würde, eine kompliziertere Funktion wie diese zu definieren, würde ich entweder mit der lodash-Implementierung beginnen und sie modifizieren oder möglicherweise etwas tun, das auf lodashs "isEqualWith" -Funktion basiert. Außerdem habe ich einige "kanonische JSON.stringify" -Funktionen gesehen, die die Schlüssel anordnen. Im Moment scheint die "grobe" Lösung, die ich erwähnt habe, in Ordnung zu sein, also bleibe ich dabei, bis es mir Probleme macht :) – gmr