code: function isEqual(a, b) {
        var k, checked;
  
        // Strict equals
        if (a === b) {
          return true;
        }
  
        // Compare null
        if (a === null || b === null) {
          return a === b;
        }
  
        // Compare number, boolean, string, undefined
        if (typeof a !== "object" || typeof b !== "object") {
          return a === b;
        }
  
        // Compare arrays
        if (Tools.isArray(b)) {
          if (a.length !== b.length) {
            return false;
          }
  
          k = a.length;
          while (k--) {
            if (!isEqual(a[k], b[k])) {
              return false;
            }
          }
        }
  
        // Shallow compare nodes
        if (isNode(a) || isNode(b)) {
          return a === b;
        }
  
        // Compare objects
        checked = {};
        for (k in b) {
          if (!isEqual(a[k], b[k])) {
            return false;
          }
  
          checked[k] = true;
        }
  
        for (k in a) {
          if (!checked[k] && !isEqual(a[k], b[k])) {
            return false;
          }
        }
  
        return true;
      }
docs: Todo: Maybe this should be shallow compare since it might be huge object references