code: function compare(value1, value2) {
    if (value1 === value2) {
      return true;
    }
    /* eslint-disable no-self-compare */
    // if both values are NaNs return true
    if ((value1 !== value1) && (value2 !== value2)) {
      return true;
    }
    if ({}.toString.call(value1) != {}.toString.call(value2)) {
      return false;
    }
    if (value1 !== Object(value1)) {
      // non equal primitives
      return false;
    }
    if (!value1) {
      return false;
    }
    if (Array.isArray(value1)) {
      return compareArrays(value1, value2);
    }
    if ({}.toString.call(value1) == '[object Object]') {
      return compareObjects(value1, value2);
    } else {
      return compareNativeSubtypes(value1, value2);
    }
  }
docs: /*
  primitives: value1 === value2
  functions: value1.toString == value2.toString
  arrays: if length, sequence and values of properties are identical
  objects: if length, names and values of properties are identical
  compare([[1, [2, 3]], [[1, [2, 3]]); // true
  compare([[1, [2, 3], 4], [[1, [2, 3]]); // false
  compare({a: 2, b: 3}, {a: 2, b: 3}); // true
  compare({a: 2, b: 3}, {b: 3, a: 2}); // true
  compare({a: 2, b: 3, c: 4}, {a: 2, b: 3}); // false
  compare({a: 2, b: 3}, {a: 2, b: 3, c: 4}); // false
  compare([[1, [2, {a: 4}], 4], [[1, [2, {a: 4}]]); // true