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

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


当前回答

这是一个简单的Javascript函数,用于比较具有简单键值对的两个对象。该函数将返回一个字符串数组,其中每个字符串是到两个对象之间的一个不等式的路径。

function compare(a,b) {
    var paths = [];
    [...new Set(Object.keys(a).concat(Object.keys(b)))].forEach(key=>{
        if(typeof a[key] === 'object' && typeof b[key] === 'object') {
            var results = compare(a[key], b[key]);
            if(JSON.stringify(results)!=='[]') {
                paths.push(...results.map(result=>key.concat("=>"+result)));
            }
        }
        else if (a[key]!==b[key]) {
            paths.push(key);
        }
    })
    return paths;
}

如果你只想比较两个对象,而不知道不等式的路径,你可以这样做:

if(JSON.stringify(compare(object1, object2))==='[]') {
   // the two objects are equal
} else {
   // the two objects are not equal
}

其他回答

最简单和逻辑的解决方案,比较一切像对象,数组,字符串,Int…

JSON。stringify({a: val1}) == JSON。stringify ({a: val2})

注意:

你需要用你的Object替换val1和val2 对于对象,必须对两侧对象进行递归排序(按键)

let user1 = { name: "John", address: { line1: "55 Green Park Road", line2: { a:[1,2,3] } }, email:null } let user2 = { name: "John", address: { line1: "55 Green Park Road", line2: { a:[1,2,3] } }, email:null } // Method 1 function isEqual(a, b) { return JSON.stringify(a) === JSON.stringify(b); } // Method 2 function isEqual(a, b) { // checking type of a And b if(typeof a !== 'object' || typeof b !== 'object') { return false; } // Both are NULL if(!a && !b ) { return true; } else if(!a || !b) { return false; } let keysA = Object.keys(a); let keysB = Object.keys(b); if(keysA.length !== keysB.length) { return false; } for(let key in a) { if(!(key in b)) { return false; } if(typeof a[key] === 'object') { if(!isEqual(a[key], b[key])) { return false; } } else { if(a[key] !== b[key]) { return false; } } } return true; } console.log(isEqual(user1,user2));

在对象中(没有方法),我们需要检查嵌套的对象,数组和基本类型。对象可以有其他对象和数组(数组也可以包括其他对象和数组),所以我们可以使用如下所示的递归函数: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
}

纯JS方法:我的答案是基于生成一个返回相同值的字符串,无论属性顺序是否相同。设置对象可用于切换大小写和空白是否重要。(为了避免失去焦点,我没有包括那些支持函数,或者我猜应该在任何实用程序集中的isObject。)

这里也没有显示,但为了减少字符串比较时间,如果对象很大,你想加快比较,你也可以散列字符串和比较子字符串;这只适用于非常大的对象(当然也有很小的机会出现错误的相等)。

然后你可以比较genObjStr(obj1) ?= genObjStr(obj2)

function genObjStr(obj, settings) {
// Generate a string that corresponds to an object guarenteed to be the same str even if
// the object have different ordering. The string would largely be used for comparison purposes

var settings = settings||{};
var doStripWhiteSpace = defTrue(settings.doStripWhiteSpace);
var doSetLowerCase = settings.doSetLowerCase||false;

if(isArray(obj)) {
    var vals = [];
    for(var i = 0; i < obj.length; ++i) {
        vals.push(genObjStr(obj[i], settings));
    }
    vals = arraySort(vals);
    return vals.join(`,`);

} else if(isObject(obj)) {

    var keys = Object.keys(obj);
    keys = arraySort(keys);

    var vals = [];
    for(var key of keys) {
        
        var value = obj[key];
        
        value = genObjStr(value, settings);

        if(doStripWhiteSpace) {
            key = removeWhitespace(key);
            var value = removeWhitespace(value);
        };
        if(doSetLowerCase) {
            key = key.toLowerCase();
            value = value.toLowerCase();
        }

        vals.push(value);
    }
    var str = JSON.stringify({keys: keys, vals: vals});
    return str
} else {
    if(doStripWhiteSpace) {
        obj = removeWhitespace(obj);
    };
    if(doSetLowerCase) {
        obj = obj.toLowerCase();
    }
    return obj
}

}

var obj1 = {foo: 123, bar: `Test`};
var obj2 = {bar: `Test`, foo: 123};

console.log(genObjStr(obj1) == genObjStr(obj1))

我写这个方法只是为了确保数组和对象都能被清晰地比较。

这应该也能做到!:)

public class Objects {
    /**
     * Checks whether a value is of type Object
     * @param value the value
     */
    public static isObject = (value: any): boolean => {
        return value === Object(value) && Object.prototype.toString.call(value) !== '[object Array]'
    }

    /**
     * Checks whether a value is of type Array
     * @param value the value
     */
    public static isArray = (value: any): boolean => {
        return Object.prototype.toString.call(value) === '[object Array]' && !Objects.isObject(value)
    }

    /**
     * Check whether two values are equal
     */
    public static isEqual = (objectA: any, objectB: any) => {
        // Objects
        if (Objects.isObject(objectA) && !Objects.isObject(objectB)) {
            return false
        }
        else if (!Objects.isObject(objectA) && Objects.isObject(objectB)) {
            return false
        }
        // Arrays
        else if (Objects.isArray(objectA) && !Objects.isArray(objectB)) {
            return false
        }
        else if (!Objects.isArray(objectA) && Objects.isArray(objectB)) {
            return false
        }
        // Primitives
        else if (!Objects.isArray(objectA) && !Objects.isObject(objectA)) {
            return objectA === objectB
        }
        // Object or array
        else {
            const compareObject = (objectA: any, objectB: any): boolean => {
                if (Object.keys(objectA).length !== Object.keys(objectB).length) return false

                for (const propertyName of Object.keys(objectA)) {
                    const valueA = objectA[propertyName]
                    const valueB = objectB[propertyName]

                    if (!Objects.isEqual(valueA, valueB)) {
                        return false
                    }
                }

                return true
            }
            const compareArray = (arrayA: any[], arrayB: any[]): boolean => {
                if (arrayA.length !== arrayB.length) return false

                for (const index in arrayA) {
                    const valueA = arrayA[index]
                    const valueB = arrayB[index]

                    if (!Objects.isEqual(valueA, valueB)) {
                        return false
                    }
                }

                return true
            }
            if (Objects.isObject(objectA)) {
                return compareObject(objectA, objectB)
            } else {
                return compareArray(objectA, objectB)
            }
        }
    }
}