Maison >interface Web >js tutoriel >Comment comparer (diff) deux objets

Comment comparer (diff) deux objets

DDD
DDDoriginal
2024-10-23 19:44:02907parcourir

How to Compare (diff) two Objects

Comparaison d'objets en JavaScript

La comparaison d'objets en JavaScript est d'une complexité trompeuse. Bien que comparer des valeurs primitives telles que des nombres et des chaînes soit simple, comparer des objets peut conduire à des résultats inattendus. Explorons différentes approches de comparaison d'objets et construisons une solution robuste pour détecter les changements entre les objets.

Les pièges de la comparaison directe

Lorsque les développeurs rencontrent pour la première fois la comparaison d'objets en JavaScript, ils essaient souvent quelque chose comme ceci :

const user1 = { name: "John", age: 30 };
const user2 = { name: "John", age: 30 };

console.log(user1 === user2); // false

Étonnamment, cela renvoie false même si les deux objets ont un contenu identique. Cela se produit parce que JavaScript compare les références d'objets, et non leurs valeurs. Les deux objets pointent vers des emplacements différents en mémoire.

Approches de comparaison simples

1. JSON.stringify

Un moyen rapide de comparer des objets consiste à utiliser JSON.stringify :

const areEqual = (obj1, obj2) => 
  JSON.stringify(obj1) === JSON.stringify(obj2);

console.log(areEqual(user1, user2)); // true

Bien que cela fonctionne pour des cas simples, cela a des limites :

  • Ne gère pas les fonctions
  • L'ordre des propriétés compte
  • Impossible de gérer les références circulaires
  • Ne fournit pas d'informations sur ce qui est différent

2. Construire une meilleure différence d'objet

Créons une solution plus sophistiquée qui non seulement détecte les différences, mais nous indique également ce qui a changé :

function getObjectDiff(original, current) {
  const changes = {};

  // Check current object's properties
  for (const [key, value] of Object.entries(current)) {
    if (!(key in original)) {
      changes[key] = {
        oldValue: undefined,
        newValue: value
      };
      continue;
    }

    const originalValue = original[key];
    const currentValue = value;

    // Handle different types of comparisons
    if (
      originalValue !== currentValue &&
      String(originalValue) !== String(currentValue) &&
      JSON.stringify(originalValue) !== JSON.stringify(currentValue)
    ) {
      changes[key] = {
        oldValue: originalValue,
        newValue: currentValue
      };
    }
  }

  // Check for removed properties
  for (const key of Object.keys(original)) {
    if (!(key in current)) {
      changes[key] = {
        oldValue: original[key],
        newValue: undefined
      };
    }
  }

  return Object.keys(changes).length === 0 ? null : changes;
}

Cette implémentation :

  • Renvoie null lorsque les objets sont identiques
  • Gère la coercition de type (par exemple, "30" contre 30)
  • Détecte les propriétés ajoutées et supprimées
  • Fournit des informations détaillées sur les modifications

Applications du monde réel

Ce type de comparaison d'objets est particulièrement utile pour :

  1. Suivi des modifications de formulaire : Détectez les champs modifiés dans un formulaire
const originalForm = { name: "John", email: "john@example.com" };
const currentForm = { name: "John", email: "john.doe@example.com" };
console.log(getObjectDiff(originalForm, currentForm));
// Output: { email: { oldValue: "john@example.com", newValue: "john.doe@example.com" } }
  1. Gestion de l'état : suivez les parties de l'état de votre application qui ont changé
  2. Mises à jour de l'API : Déterminez les champs à envoyer dans les requêtes PATCH
  3. Journalisation d'audit : enregistre les modifications spécifiques apportées aux données

Cas Edge (dans lesquels vous devrez peut-être faire un effort supplémentaire)

  1. Objets imbriqués : comparaison approfondie vs comparaison superficielle
  2. Tableaux : Sensibilité de l'ordre et comparaison de référence
  3. Coercition de type : comparaisons de chaînes et de nombres
  4. Valeurs spéciales : non défini, nul, NaN
  5. Performance : Une comparaison approfondie peut être coûteuse pour les gros objets

PS : Voici un aperçu Github d'une fonction simple pour comparer et obtenir la différence entre deux objets :

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn