Voici mon ES3 solution commentée (détails gores après le code) :
function object_equals( x, y ) {
if ( x === y ) return true;
// if both x and y are null or undefined and exactly the same
if ( ! ( x instanceof Object ) || ! ( y instanceof Object ) ) return false;
// if they are not strictly equal, they both need to be Objects
if ( x.constructor !== y.constructor ) return false;
// they must have the exact same prototype chain, the closest we can do is
// test there constructor.
for ( var p in x ) {
if ( ! x.hasOwnProperty( p ) ) continue;
// other properties were tested using x.constructor === y.constructor
if ( ! y.hasOwnProperty( p ) ) return false;
// allows to compare x[ p ] and y[ p ] when set to undefined
if ( x[ p ] === y[ p ] ) continue;
// if they have the same strict value or identity then they are equal
if ( typeof( x[ p ] ) !== "object" ) return false;
// Numbers, Strings, Functions, Booleans must be strictly equal
if ( ! object_equals( x[ p ], y[ p ] ) ) return false;
// Objects and Arrays must be tested recursively
}
for ( p in y )
if ( y.hasOwnProperty( p ) && ! x.hasOwnProperty( p ) )
return false;
// allows x[ p ] to be set to undefined
return true;
}
En développant cette solution, j'ai porté un regard particulier sur les cas de figure, l'efficacité, tout en essayant de produire une solution simple qui fonctionne, avec, je l'espère, une certaine élégance. JavaScript permet à la fois null y indéfini les propriétés et les objets ont chaînes de prototypes qui peuvent conduire à des comportements très différents s'ils ne sont pas vérifiés.
D'abord, j'ai choisi de ne pas prolonger Objet.prototype surtout parce que null ne pouvait pas être un des objets de la comparaison et que je crois que null devrait être un objet valable à comparer avec un autre. Il y a également d'autres préoccupations légitimes notées par d'autres personnes concernant l'extension de l'application de la loi sur la protection de l'environnement. Objet.prototype concernant les effets secondaires possibles sur le code des autres.
Une attention particulière doit être apportée à la possibilité que JavaScript permette aux propriétés de l'objet d'être définies comme suit indéfini c'est-à-dire qu'il existe des propriétés dont les valeurs sont fixées à indéfini . La solution ci-dessus permet de vérifier que les deux objets ont les mêmes propriétés définies à indéfini pour signaler l'égalité. Ceci ne peut être accompli qu'en vérifiant l'existence des propriétés à l'aide de Object.hasOwnProperty( property_name ) . Notez également que JSON.stringify() supprime les propriétés qui sont définies comme indéfini et que, par conséquent, les comparaisons effectuées à l'aide de ce formulaire ne tiendront pas compte des propriétés ayant pour valeur indéfini .
Les fonctions ne doivent être considérées comme égales que si elles partagent la même référence, et pas seulement le même code, car cela ne tiendrait pas compte du prototype de ces fonctions. Ainsi, la comparaison de la chaîne de code ne permet pas de garantir qu'elles ont le même objet prototype.
Les deux objets doivent avoir le même chaîne des prototypes et pas seulement les mêmes propriétés. Ceci ne peut être testé qu'à travers les navigateurs en comparant l'image de l Constructeur des deux objets pour une stricte égalité. ECMAScript 5 permettrait de tester leur prototype réel en utilisant Objet.getPrototypeOf() . Certains navigateurs web offrent également une __proto__ qui fait la même chose. Une amélioration possible du code ci-dessus permettrait d'utiliser l'une de ces méthodes chaque fois qu'elle est disponible.
L'utilisation de comparaisons strictes est primordiale ici car 2 ne doit pas être considérée comme égale à "2.0000" ni faux doit être considéré comme égal à null , indéfini ou 0 .
Des considérations d'efficacité me conduisent à comparer pour l'égalité des propriétés dès que possible. Ensuite, seulement si cela a échoué, chercher le typeof ces propriétés. L'augmentation de la vitesse pourrait être significative sur les grands objets avec beaucoup de propriétés scalaires.
Il suffit de deux boucles, la première pour vérifier les propriétés de l'objet de gauche, la seconde pour vérifier les propriétés de l'objet de droite en ne vérifiant que l'existence (et non la valeur), pour attraper ces propriétés qui sont définies avec l'attribut indéfini valeur.
Globalement, ce code gère la plupart des cas de figure en seulement 16 lignes de code (sans commentaires).
Mise à jour (13/08/2015) . J'ai implémenté une meilleure version, car la fonction valeur_équivalente() qui est plus rapide, qui traite correctement les cas de coin comme NaN et 0 différent de -0, qui applique éventuellement l'ordre des propriétés des objets et qui teste les références cycliques, et qui est soutenue par plus de 100 tests automatisés dans le cadre du Toubkal suite de tests du projet.
2 votes
J'ai bricolé un peu sur le sujet et j'ai trouvé une solution flexible au problème. stamat.wordpress.com/2013/06/22/javascript-object-comparison
2 votes
Les tests d'égalité (profonde) sont assez difficiles à réaliser. rendez-vous sur le site github.com/loveencounterflow/jseq pour voir une suite de tests des produits populaires
equal()
qui couvre déjà de nombreux cas limites. La discussion dans la documentation est également assez approfondie.0 votes
Este pourrait être utile et/ou efficace.
0 votes
J'ai ajouté une réponse à ce sujet à : stackoverflow.com/questions/201183/ En fait, il y a beaucoup de bonnes réponses, même si c'est le premier résultat de la recherche.
53 votes
Utilisez lodash. C'est
isEqual
fait exactement ce que vous voulez.2 votes
Utiliser facebook.github.io/immutable-js et cette opération sera super facile et rapide
0 votes
J'ai trouvé un moyen facile.
function equal (x,y){ return x >= y && x <= y}
0 votes
Encore mieux :
function equal (x,y){ return !( x < y || x > y)}
. Il fonctionne correctement pour les objets, les tableaux, les nombres, les chaînes de caractères, les NaN, et même les fonctions. Attention : il coerce les types et les méthodes seront ignorées.12 votes
En utilisant l'underscore,
_.isEqual( obj1 , obj2 )
0 votes
Vous pouvez l'installer via npm : npmjs.com/package/deep-equal
0 votes
VM304:1 Uncaught TypeError: Object.toJSON is not a function
0 votes
Je pense que l'on peut comparer toutes les choses en ne considérant que
function _isEqual(val, oval) { return (JSON.stringify({a: val}) === JSON.stringify({a: oval})) }
0 votes
Il existe une solution plus élégante : kcak11.github.io/jslib/deepCompareObjects.js Celui-ci est plus facile à comprendre et fait le travail ! !!
0 votes
Voici une méthode simple pour comparer deux objets : var user1 = {name : "nerd", org : "dev"} ; var user2 = {name : "nerd", org : "dev"} ; console.log(JSON.stringify(user1).toString() === JSON.stringify(user2).toString()) ; // vrai
0 votes
Pour plus d'informations, veuillez vous référer à : adripofjavascript.com/blog/drips/
0 votes
JSON.stringify peut vous aider
0 votes
jsben.ch/1uLAP <= comparaison des performances entre JSON.stringify et fast-deep-equal