How can I get a list of the differences between two JavaScript object graphs?

前端 未结 10 583
终归单人心
终归单人心 2020-11-29 01:02

I want to be able to get a list of all differences between two JavaScript object graphs, with the property names and values where the deltas occur.

For what it is w

10条回答
  •  难免孤独
    2020-11-29 01:30

    Solution 1

    Use JSON.stringify(obj) to get a string representation of the objects you want to compare. Save the string to a file. Use any diff viewer to compare the text files.

    Note: JSON.stringify will ignore properties that point to function definitions.

    Solution 2

    This could do what you want with some modification, it is a modified version of the function _.isEqual (http://documentcloud.github.com/underscore/). Please feel free to suggest any modifications! I wrote it to figure out where the first difference between two objects occur.

    // Given two objects find the first key or value not matching, algorithm is a
    // inspired by of _.isEqual.
    function diffObjects(a, b) {
      console.info("---> diffObjects", {"a": a, "b": b});
      // Check object identity.
      if (a === b) return true;
      // Different types?
      var atype = typeof(a), btype = typeof(b);
      if (atype != btype) {
        console.info("Type mismatch:", {"a": a, "b": b});
        return false;
      };
      // Basic equality test (watch out for coercions).
      if (a == b) return true;
      // One is falsy and the other truthy.
      if ((!a && b) || (a && !b)) {
        console.info("One is falsy and the other truthy:", {"a": a, "b": b});
        return false;
      }
      // Unwrap any wrapped objects.
      if (a._chain) a = a._wrapped;
      if (b._chain) b = b._wrapped;
      // One of them implements an isEqual()?
      if (a.isEqual) return a.isEqual(b);
      // Check dates' integer values.
      if (_.isDate(a) && _.isDate(b)) return a.getTime() === b.getTime();
      // Both are NaN?
      if (_.isNaN(a) && _.isNaN(b)) {
        console.info("Both are NaN?:", {"a": a, "b": b});
        return false;
      }
      // Compare regular expressions.
      if (_.isRegExp(a) && _.isRegExp(b))
        return a.source     === b.source &&
               a.global     === b.global &&
               a.ignoreCase === b.ignoreCase &&
               a.multiline  === b.multiline;
      // If a is not an object by this point, we can't handle it.
      if (atype !== 'object') {
        console.info("a is not an object:", {"a": a});
        return false;
      }
      // Check for different array lengths before comparing contents.
      if (a.length && (a.length !== b.length)) {
        console.info("Arrays are of different length:", {"a": a, "b": b});
        return false;
      }
      // Nothing else worked, deep compare the contents.
      var aKeys = _.keys(a), bKeys = _.keys(b);
      // Different object sizes?
      if (aKeys.length != bKeys.length) {
        console.info("Different object sizes:", {"a": a, "b": b});
        return false;
      }
      // Recursive comparison of contents.
      for (var key in a) if (!(key in b) || !diffObjects(a[key], b[key])) return false;
      return true;
    };
    

提交回复
热议问题