Skip to content

Instantly share code, notes, and snippets.

@yijian166
Created May 21, 2014 03:44
Show Gist options
  • Select an option

  • Save yijian166/934ce36673921d8af8e2 to your computer and use it in GitHub Desktop.

Select an option

Save yijian166/934ce36673921d8af8e2 to your computer and use it in GitHub Desktop.

Revisions

  1. yijian166 created this gist May 21, 2014.
    123 changes: 123 additions & 0 deletions gistfile1.js
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,123 @@
    //1) https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is
    var isSame = Object.is(value1, value2);

    //2) Fast and limited.
    //The ORDER of the properties IS IMPORTANT

    JSON.stringify(obj1) === JSON.stringify(obj2) ;

    //3) Slow and more generic.
    function deepCompare () {
    var leftChain, rightChain;

    function compare2Objects (x, y) {
    var p;

    // remember that NaN === NaN returns false
    // and isNaN(undefined) returns true
    if (isNaN(x) && isNaN(y) && typeof x === 'number' && typeof y === 'number') {
    return true;
    }

    // Compare primitives and functions.
    // Check if both arguments link to the same object.
    // Especially useful on step when comparing prototypes
    if (x === y) {
    return true;
    }

    // Works in case when functions are created in constructor.
    // Comparing dates is a common scenario. Another built-ins?
    // We can even handle functions passed across iframes
    if ((typeof x === 'function' && typeof y === 'function') ||
    (x instanceof Date && y instanceof Date) ||
    (x instanceof RegExp && y instanceof RegExp) ||
    (x instanceof String && y instanceof String) ||
    (x instanceof Number && y instanceof Number)) {
    return x.toString() === y.toString();
    }

    // At last checking prototypes as good a we can
    if (!(x instanceof Object && y instanceof Object)) {
    return false;
    }

    if (x.isPrototypeOf(y) || y.isPrototypeOf(x)) {
    return false;
    }

    if (x.constructor !== y.constructor) {
    return false;
    }

    if (x.prototype !== y.prototype) {
    return false;
    }

    // check for infinitive linking loops
    if (leftChain.indexOf(x) > -1 || rightChain.indexOf(y) > -1) {
    return false;
    }

    // Quick checking of one object beeing a subset of another.
    // todo: cache the structure of arguments[0] for performance
    for (p in y) {
    if (y.hasOwnProperty(p) !== x.hasOwnProperty(p)) {
    return false;
    }
    else if (typeof y[p] !== typeof x[p]) {
    return false;
    }
    }

    for (p in x) {
    if (y.hasOwnProperty(p) !== x.hasOwnProperty(p)) {
    return false;
    }
    else if (typeof y[p] !== typeof x[p]) {
    return false;
    }

    switch (typeof (x[p])) {
    case 'object':
    case 'function':

    leftChain.push(x);
    rightChain.push(y);

    if (!compare2Objects (x[p], y[p])) {
    return false;
    }

    leftChain.pop();
    rightChain.pop();
    break;

    default:
    if (x[p] !== y[p]) {
    return false;
    }
    break;
    }
    }

    return true;
    }

    if (arguments.length < 1) {
    return true; //Die silently? Don't know how to handle such case, please help...
    // throw "Need two or more arguments to compare";
    }

    for (var i = 1, l = arguments.length; i < l; i++) {

    leftChain = []; //todo: this can be cached
    rightChain = [];

    if (!compare2Objects(arguments[0], arguments[i])) {
    return false;
    }
    }

    return true;
    }