JS判断两个对象是否相等

4,792 阅读1分钟

前言

在做项目优化时,需要用到判断两对象是否一致逻辑,所以自己询着逻辑写了一下,现将它写为文档,以供日后自己查阅

1. 字符串比较

此种情况只适用于两个property顺序完全一致的对象判断

// 1. same order same property
function isObjStringEqual(obj1, obj2) { 
    return JSON.stringify(obj1) === JSON.stringify(obj2);
}

2. 浅比较

只做第一层数据的查询,跳过数组、对象、方法

利用es6的every函数做最优处理

// 2. shallow compare
function isObjShallowEqual(obj1, obj2) {
    const keys1 = Object.getOwnPropertyNames(obj1);
    const keys2 = Object.getOwnPropertyNames(obj2);
    if (keys1.length !== keys2.length) {
        return false;
    }
    const flag = keys1.every(key => {
        const type = typeof obj1[key];
        // do not check function, array, object
        if (['function', 'array', 'object'].includes(type)) {
            return type === typeof obj2[key];
        }
        // if unequal, return true
        if (obj1[key] !== obj2[key]) {
            return false;
        }
        return true;
    });
    // if found unequal, then return false, which means unequal
    return flag;
}

3. 深比较

对array和object做比较,只比较第二层子集,如果array里面再套array或者object,不作处理

// 3. deep compare
function isObjDeepEqual(obj1, obj2) {
    const KEY = {
        OBJECT: 'object',
        ARRAY: 'array',
        FUNCTION: 'function',
    };
    const keys1 = Object.getOwnPropertyNames(obj1);
    const keys2 = Object.getOwnPropertyNames(obj2);
    if (keys1.length !== keys2.length) {
        return false;
    }
    const flag = keys1.every(key => {
        const TYPE = typeof obj1[key];
        // escape null && self-call the function
        if (!!obj1[key] && TYPE === KEY.OBJECT) {
            return isObjDeepEqual(obj1[key], obj2[key]); // the recursion of funciton call
        }
        // array's case
        if (TYPE === KEY.ARRAY) {
            // check the length
            if (obj1[key].length !== obj2[key].length) {
                return false;
            }
            return obj1[key].every((child, index) => {
                const CHILD_TYPE = typeof child;
                // skip more deep compare, limit to 2
                if ([KEY.ARRAY].includes(CHILD_TYPE)) {
                    return true;
                }
                // if function or object, then self-call
                if ([KEY.OBJECT, KEY.FUNCTION].includes(CHILD_TYPE)) {
                    const OBJ2_CHILD = obj2[key][index];
                    if (CHILD_TYPE !== typeof OBJ2_CHILD) {
                        return false;
                    }
                    return isObjDeepEqual(child, OBJ2_CHILD);
                }
                // Normal value check
                if (child !== obj2[key][index]) {
                    return false;
                }
                return true;
            });
        }
        // convert function to string, then compare the value
        if (TYPE === KEY.FUNCTION) {
            return obj1[key].toString() === obj2[key].toString();
        }
        // if unequal, return true
        if (obj1[key] !== obj2[key]) {
            return false;
        }
        return true;
    });
    // if found unequal, then return
    return flag;
}