两个对象比较是否相等

let a= {
    id:1,
    hobby:[1,3]
}

let b= {
    id:1,
    hobby:[1,2,3]
}

js怎么去判断 a 和 b 是否相等 ,对象中 的 value 可能是字符串,数组 对象等

阅读 7.4k
6 个回答

JavaScript专题之如何判断两个对象相等
文章中解释的很详细,直接用了他最终的 eq 函数可以实现比较。

以下代码是原文中最终的 eq 函数代码:

    return toString.call(obj) === '[object Function]' }

function eq(a, b, aStack, bStack) {

    // === 结果为 true 的区别出 +0 和 -0
    if (a === b) return a !== 0 || 1 / a === 1 / b;

    // typeof null 的结果为 object ,这里做判断,是为了让有 null 的情况尽早退出函数
    if (a == null || b == null) return false;

    // 判断 NaN
    if (a !== a) return b !== b;

    // 判断参数 a 类型,如果是基本类型,在这里可以直接返回 false
    var type = typeof a;
    if (type !== 'function' && type !== 'object' && typeof b != 'object') return false;

    // 更复杂的对象使用 deepEq 函数进行深度比较
    return deepEq(a, b, aStack, bStack); };

function deepEq(a, b, aStack, bStack) {

    // a 和 b 的内部属性 [[class]] 相同时 返回 true
    var className = toString.call(a);
    if (className !== toString.call(b)) return false;

    switch (className) {
        case '[object RegExp]':
        case '[object String]':
            return '' + a === '' + b;
        case '[object Number]':
            if (+a !== +a) return +b !== +b;
            return +a === 0 ? 1 / +a === 1 / b : +a === +b;
        case '[object Date]':
        case '[object Boolean]':
            return +a === +b;
    }

    var areArrays = className === '[object Array]';
    // 不是数组
    if (!areArrays) {
        // 过滤掉两个函数的情况
        if (typeof a != 'object' || typeof b != 'object') return false;

        var aCtor = a.constructor,
            bCtor = b.constructor;
        // aCtor 和 bCtor 必须都存在并且都不是 Object 构造函数的情况下,aCtor 不等于 bCtor, 那这两个对象就真的不相等啦
        if (aCtor !== bCtor && !(isFunction(aCtor) && aCtor instanceof aCtor && isFunction(bCtor) && bCtor instanceof bCtor) &&
('constructor' in a && 'constructor' in b)) {
            return false;
        }
    }


    aStack = aStack || [];
    bStack = bStack || [];
    var length = aStack.length;

    // 检查是否有循环引用的部分
    while (length--) {
        if (aStack[length] === a) {
            return bStack[length] === b;
        }
    }

    aStack.push(a);
    bStack.push(b);

    // 数组判断
    if (areArrays) {

        length = a.length;
        if (length !== b.length) return false;

        while (length--) {
            if (!eq(a[length], b[length], aStack, bStack)) return false;
        }
    }
    // 对象判断
    else {

        var keys = Object.keys(a),
            key;
        length = keys.length;

        if (Object.keys(b).length !== length) return false;
        while (length--) {

            key = keys[length];
            if (!(b.hasOwnProperty(key) && eq(a[key], b[key], aStack, bStack))) return false;
        }
    }

    aStack.pop();
    bStack.pop();
    return true;

}

使用:

let a= {
    id:1,
    hobby:[1,3]
}

let b= {
    id:1,
    hobby:[1,2,3]
}
let c= {
    hobby:[1,3],
    id:1,
}
let d= {
    hobby:[1,2,3],
    id:1,
}

eq(a,b) //结果为false
eq(a,c) //true
eq(a,d) //false
eq(b,c) //false
eq(b,d) //true
eq(c,d) //false

看了其他人的几个回答,感觉这篇文章里的这个方法真的是很强大的了。
也顺便学习了下。
^_^

首先JSON.stringify是不可能的,其次这种经典问题到处都能找到。object-comparison-in-javascript

 x = {a: 1, b: 2};
 y = {b: 2, a: 1};
 JSON.stringify(x)===JSON.stringify(y); //false

常见比较相等的办法应该是循环对象属性了吧,不过很慢的。JSON.stringify局限性太高了,属性次序不一样的话是不可以的。

let a= {
    id:1,
    hobby:[1,2,3]
}

let b = {
    hobby:[1,2,3],
    id:1,
}
function keySort(target){
    const newObj = {}
    Object.keys(target).sort().map(key => newObj[key] = target[key])
    return newObj
}
console.log(JSON.stringify(keySort(a)) === JSON.stringify(keySort(b)))  // true

为啥要喷JSON.stringify,不支持排序不能把它排了再拿出来用吗(手动狗头)

是深是浅?

深的话直接使用JSON.stringify

浅的话使用Object.keys

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题