严格相等运算符将告诉您两个对象类型是否相等。然而,是否有一种方法来判断两个对象是否相等,就像Java中的哈希码值一样?

堆栈溢出问题JavaScript中有hashCode函数吗?类似于这个问题,但需要一个更学术的答案。上面的场景说明了为什么有必要有一个,我想知道是否有等效的解决方案。


当前回答

Stringify两个对象并进行比较

返回(JSON.stringify(obj1) === = JSON.stringify(obj2))

这将返回true或false

其他回答

我需要模拟jQuery POST请求,因此对我来说重要的是两个对象具有相同的属性集(任何一个对象中都不缺少属性),并且每个属性值都是“相等的”(根据这个定义)。我不关心对象是否有不匹配的方法。

这是我将使用的,它应该足以满足我的特定要求:

function PostRequest() {
    for (var i = 0; i < arguments.length; i += 2) {
        this[arguments[i]] = arguments[i+1];
    }

    var compare = function(u, v) {
        if (typeof(u) != typeof(v)) {
            return false;
        }

        var allkeys = {};
        for (var i in u) {
            allkeys[i] = 1;
        }
        for (var i in v) {
            allkeys[i] = 1;
        }
        for (var i in allkeys) {
            if (u.hasOwnProperty(i) != v.hasOwnProperty(i)) {
                if ((u.hasOwnProperty(i) && typeof(u[i]) == 'function') ||
                    (v.hasOwnProperty(i) && typeof(v[i]) == 'function')) {
                    continue;
                } else {
                    return false;
                }
            }
            if (typeof(u[i]) != typeof(v[i])) {
                return false;
            }
            if (typeof(u[i]) == 'object') {
                if (!compare(u[i], v[i])) {
                    return false;
                }
            } else {
                if (u[i] !== v[i]) {
                    return false;
                }
            }
        }

        return true;
    };

    this.equals = function(o) {
        return compare(this, o);
    };

    return this;
}

像这样使用:

foo = new PostRequest('text', 'hello', 'html', '<p>hello</p>');
foo.equals({ html: '<p>hello</p>', text: 'hello' });

另外一个选项是使用Ramda库的equals:

const c = {a: 1, b: 2};
const d = {b: 2, a: 1};
R.equals(c, d); //=> true

我建议不要使用散列或序列化(正如JSON解决方案所建议的那样)。如果需要测试两个对象是否相等,则需要定义相等的含义。这可能是两个对象中的所有数据成员都匹配,也可能是内存位置必须匹配(意味着两个变量在内存中引用同一个对象),或者每个对象中只有一个数据成员必须匹配。

最近我开发了一个对象,它的构造函数在每次创建实例时都会创建一个新的id(从1开始,加1)。该对象有一个isEqual函数,用于将该id值与另一个对象的id值进行比较,如果匹配则返回true。

在这种情况下,我定义“相等”的意思是id值匹配。假设每个实例都有一个唯一的id,这可以用来加强匹配对象也占用相同内存位置的想法。尽管这是不必要的。

在对象中(没有方法),我们需要检查嵌套的对象,数组和基本类型。对象可以有其他对象和数组(数组也可以包括其他对象和数组),所以我们可以使用如下所示的递归函数:arrayEquals检查数组是否相等,equals检查对象是否相等:

function arrayEquals(a, b) {
    if (a.length != b.length) {
        return false;
    }
    for (let i = 0; i < a.length; i++) {
        if (a[i].constructor !== b[i].constructor) {
            return false;
        }

        if (a[i] instanceof Array && b[i] instanceof Array) {
            if (!arrayEquals(a, b)) {
                return false;
            }
        } else if (a[i] instanceof Object && b[i] instanceof Object) {
            if (!equals(a[i], b[i])) {
                return false;
            }
        } else if (a[i] !== b[i]) {
            return false;
        }
    }
    return true;
}

function equals(a, b) {
    for (let el in a) {
        if (b.hasOwnProperty(el)) {
            if (a[el].constructor !== b[el].constructor) {
                return false;
            }

            if (a[el] instanceof Array && b[el] instanceof Array) {
                if (!arrayEquals(a[el], b[el])) {
                    return false;
                }
            } else if (a[el] instanceof Object && b[el] instanceof Object) {
                if (!equals(a[el], b[el])) {
                    return false;
                }
            } else if (a[el] !== b[el]) {
                return false;
            }
        } else {
            return false;
        }
    }
    return true;
}

假设你有两个对象:

let a = {
    a: 1,
    b: { c: 1, d: "test" },
    c: 3,
    d: [{ a: [1, 2], e: 2 }, "test", { c: 3, q: 5 }],
};

let b = {
    a: 1,
    b: { c: 1, d: "test" },
    c: 3,
    d: [{ a: [1, 2], e: 2 }, "test", { c: 3, q: 5 }],
};

在这里使用上面的equals函数,你可以很容易地比较这两个对象,像这样:

if(equals(a, b)) {
    // do whatever you want
}

我已经实现了一个方法,它接受两个json,并使用递归检查它们的键是否具有相同的值。 我用另一个问题来解决这个问题。

const arraysEqual = (a, b) => { if (a === b) return true; if (a === null || b === null) return false; if (a.length !== b.length) return false; // If you don't care about the order of the elements inside // the array, you should sort both arrays here. for (let i = 0; i < a.length; ++i) { if (a[i] !== b[i]) return false; } return true; }; const jsonsEqual = (a, b) => { if(typeof a !== 'object' || typeof b !== 'object') return false; if (Object.keys(a).length === Object.keys(b).length) { // if items have the same size let response = true; for (let key in a) { if (!b[key]) // if not key response = false; if (typeof a[key] !== typeof b[key]) // if typeof doesn't equals response = false; else { if (Array.isArray(a[key])) // if array response = arraysEqual(a[key], b[key]); else if (typeof a[key] === 'object') // if another json response = jsonsEqual(a[key], b[key]); else if (a[key] !== b[key]) // not equals response = false; } if (!response) // return if one item isn't equal return false; } } else return false; return true; }; const json1 = { a: 'a', b: 'asd', c: [ '1', 2, 2.5, '3', { d: 'asd', e: [ 1.6, { f: 'asdasd', g: '123' } ] } ], h: 1, i: 1.2, }; const json2 = { a: 'nops', b: 'asd' }; const json3 = { a: 'h', b: '484', c: [ 3, 4.5, '2ss', { e: [ { f: 'asdasd', g: '123' } ] } ], h: 1, i: 1.2, }; const result = jsonsEqual(json1,json2); //const result = jsonsEqual(json1,json3); //const result = jsonsEqual(json1,json1); if(result) // is equal $('#result').text("Jsons are the same") else $('#result').text("Jsons aren't equals") <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <div id="result"></div>