2017-07-23 4 views
0

Modifier: Ce n'est pas une question en double. Ma fonction est différente et n'utilise pas les méthodes de comparaison directe d'objet.Comparer les types, les valeurs et les objets en JavaScript (pas un doublon)

Je travaille sur le livre Javascript éloquent et dans le quatrième chapitre, le dernier exercice nécessitait une fonction deepEqual qui prend deux arguments et les compare.

  • Si les arguments sont de types différents, il doit renvoyer false.
  • Si les arguments sont du même type et de la même valeur, il doit renvoyer sinon, renvoyer false.
  • Si les arguments sont à la fois des objets, leurs propriétés et valeurs doivent être comparées. L'appel de fonction doit renvoyer true si les deux objets ont les mêmes propriétés et valeurs dans le même ordre. Par exemple, si nous avons les objets suivants: object1 = {a: 1, b: 2}, object2 = {a: 1, b: 2}, object3 = {a: 2, b: 1}, la comparaison de object1 et object2 doit renvoyer true, mais la comparaison de object1 et object3 doit renvoyer false.
  • Enfin, si les objets ont des objets imbriqués en tant que paramètres, un appel récursif de deepEqual permet de comparer les objets imbriqués.

Donc, voici ma solution. Il est assez compliqué avec les instructions if/else, pardonnez-le.

function deepEqual(obj1, obj2){ 

    var checkForSameTypes = (typeof obj1 === typeof obj2); 

    if(checkForSameTypes === true){ 

    //same type but not objects 
    if(typeof obj1 !== "object" && typeof obj2 !== "object") { 
     if(obj1 == obj2){ 
     return true; 
     }else{ 
     return false; 
     } 

    // same type and objects 
    }else if(typeof obj1 === "object" && typeof obj2 === "object"){ 

     //loop first object and compare properties with 2nd object 
     for(var prop in obj1){ 
     if(obj2.hasOwnProperty(prop)) { 

     //if 2nd object has property "prop" compare 
      if(typeof obj1[prop] === "object" && typeof obj2[prop] === "object"){ 
      //recursive call 
      deepEqual(obj1[prop], obj2[prop]); 
      }else if(obj1[prop] === obj2[prop]) { 
      //loop goes on to the next property 
      continue; 
      }else if(obj1[prop] !== obj2[prop]){ 
      return false; 
      } 
     //it doesn't have property "prop" so return false 
     } else { 
      return false; 
     } 
     } 
     //finishes loop and all properties are the same 
     return true; 
    } 
    // they are not the same types so return false 
    } else { 
    return false; 
    } 
} 

PROBLÈME

La fonction fonctionne très bien, sauf si un argument est un objet avec des objets imbriqués. Prenez ces objets par exemple

var type = {go: {inside: "yes"}, come: 2} 

var see = {go: {inside: "no"}, come: 2} 

var fine = {when: 3, go: 4};` 

Quand je compare type et see avec un appel à deepEqual(type,see);, cela renvoie true ce qui est faux parce que la valeur de la propriété de l'objet imbriqué go est différent.

J'ai parcouru tout le code sur papier, ligne par ligne et je ne sais pas ce que je dois faire, ou si l'appel récursif ne fonctionne pas pour comparer les propriétés correctement ou que je n'en ai pas la connaissance encore.

Quelqu'un peut-il offrir une solution? ou et si possible un meilleur moyen ou un processus de réflexion pour résoudre ce cas?

Remarque: Le code compare uniquement les propriétés et les valeurs d'objet. Il n'a pas besoin de comparer des constructeurs ou des prototypes.

+0

Similaire, mais pas un doublon. Mon problème est assez différent –

Répondre

0

Il existe de nombreuses techniques pour faire la comparaison d'objets en profondeur, mais sans doute le plus fiable est aussi la plus simple ... En utilisant JSON.stringify(obj) sur chaque objet à comparer, ce qui les transforme en chaînes, puis comparer les chaînes.

var a = {go: {inside: "yes"}, come: 2, flag: true} 
 
var b = {go: {inside: "yes"}, come: 2, flag: true} 
 
var c = {go: {inside: "yes"}, come: 1} 
 
var d = {go: {inside: "yes"}, come: 2, flag: "true"} 
 

 
function deepEqual(obj1, obj2){ 
 
    // Convert both objects to strings and compare them: 
 
    console.log(JSON.stringify(obj1) === JSON.stringify(obj2)); 
 
} 
 

 
deepEqual(a,b); // true 
 
deepEqual(b,c); // false 
 
deepEqual(a,d); // false

Maintenant, gardez à l'esprit que JSON.stringify() bandes de propriétés sur qui stockent des fonctions, par défaut, pour des raisons de sécurité, mais en utilisant l'argument optionnel « succédané », vous pouvez réellement persister manuellement que dans la chaîne

+0

Le problème avec ceci, c'est qu'il va considérer '{a: 1, b: 1}' différent de '{b: 1, a: 1}', et ignorer tous les objets imbriqués qui ne sont pas représentables en JSON, comme 'Set',' Map', ... etc. – trincot

+0

@trincot Points pris. –

+0

Bonjour Scott, merci pour cette réponse, malheureusement, je ne suis pas autorisé à utiliser l'abstraction comme le 'JSON.stringify()'. –