Object Diff with Underscore

by drzaus

HTML

<script src="http://underscorejs.org/underscore-min.js"></script>
<div id="debug"></div>

JavaScript

(function(_) {
  function deepDiff(a, b, r, reversible) {
    _.each(a, function(v, k) {
      // already checked this or equal...
      if (r.hasOwnProperty(k) || b[k] === v) return;
      // but what if it returns an empty object? still attach?
      r[k] = _.isObject(v) ? _.diff(v, b[k], reversible) : v;
    });
  }
  
  /* the function */
  _.mixin({
    shallowDiff: function(a, b) {
      return _.omit(a, function(v, k) {
        return b[k] === v;
      })
    },
    diff: function(a, b, reversible) {
      var r = {};
      deepDiff(a, b, r, reversible);
      if(reversible) deepDiff(b, a, r, reversible);
      return r;
    }
  });

  /* just so there's something to see */
  function dump() {
    var args = Array.prototype.slice.call(arguments);
    console.log.apply(console, args);

    var p = document.createElement('pre');
    _.each(args, function(a) {
      p.innerText += JSON.stringify(a) + '  ';
    });
    document.getElementById('debug').appendChild(p);
  }

  var o1 = {
      a: 1,
      b: 2,
      c: 2
    },
    o2 = {
      a: 2,
      b: 1,
      c: 2
    },
    o3 = {
      a: 1,
      b: 2
    };


  dump('a = ', o1);
  dump('b = ', o2);
  dump('c = ', o3);
  dump('shallowdiff(a, b) = ', _.shallowDiff(o1, o2));
  dump('shallowdiff(b, a) = ', _.shallowDiff(o2, o1));
  dump('shallowdiff(a, c) = ', _.shallowDiff(o1, o3));
  dump('shallowdiff(c, a) = ', _.shallowDiff(o3, o1));

  dump('diff(a, b) = ', _.diff(o1, o2));
  dump('diff(b, a) = ', _.diff(o2, o1));
  dump('diff(a, c) = ', _.diff(o1, o3));
  dump('diff(c, a) = ', _.diff(o3, o1));
  dump('diff(c, a, reversible) = ', _.diff(o3, o1, true));

  var o3 = {
      x: 4,
      y: 2,
      z: o1,
      zz: o1
    },
    o4 = {
      x: 56,
      y: 2,
      z: o1,
      zz: o2
    };

  dump('o3 = ', o3);
  dump('o4 = ', o4);

  dump('shallowdiff(o3, o4) = ', _.shallowDiff(o3, o4));
  dump('shallowdiff(o4, o3) = ', _.shallowDiff(o4, o3));

  dump('diff(o3, o4) = ', _.diff(o3, o4));
 ...