js对象如何深比较?

JavaScript 对象的深比较几种常见方法:

1. 使用 JSON.stringify:

这是最简单的方法之一,但有一些限制。它将对象转换为字符串进行比较,因此无法处理循环引用,并且会忽略函数和 undefined 值。

function deepEqual(obj1, obj2) {
  return JSON.stringify(obj1) === JSON.stringify(obj2);
}

let obj1 = { a: 1, b: '2' };
let obj2 = { a: 1, b: '2' };
let obj3 = { b: '2', a: 1 }; // 即使属性顺序不同,也认为是相等的

console.log(deepEqual(obj1, obj2)); // true
console.log(deepEqual(obj1, obj3)); // true

let obj4 = { a: 1, b: 2 };
console.log(deepEqual(obj1, obj4)); // false

//  limitations
let obj5 = { a: 1, b: undefined };
let obj6 = { a: 1 };
console.log(deepEqual(obj5, obj6)); // false  undefined会被忽略

let obj7 = { a: function() {} };
let obj8 = { a: function() {} };
console.log(deepEqual(obj7, obj8)); // false 函数会被忽略

2. 递归比较:

这是更稳健的方法,可以处理各种数据类型,包括嵌套对象、数组和函数。

function deepEqual(obj1, obj2) {
  if (typeof obj1 !== typeof obj2) return false;

  if (typeof obj1 === 'object') {
    if (Array.isArray(obj1)) {
      if (!Array.isArray(obj2) || obj1.length !== obj2.length) return false;
      for (let i = 0; i < obj1.length; i++) {
        if (!deepEqual(obj1[i], obj2[i])) return false;
      }
      return true;
    } else {
      const keys1 = Object.keys(obj1);
      const keys2 = Object.keys(obj2);
      if (keys1.length !== keys2.length) return false;
      for (const key of keys1) {
        if (!obj2.hasOwnProperty(key) || !deepEqual(obj1[key], obj2[key])) return false;
      }
      return true;
    }
  } else if (typeof obj1 === 'function') {
    //  比较函数通常比较复杂,可以比较函数的toString(),但并不完全可靠
    return obj1.toString() === obj2.toString();
  } else {
    return obj1 === obj2;
  }
}


let obj1 = { a: 1, b: { c: 3 } };
let obj2 = { a: 1, b: { c: 3 } };
console.log(deepEqual(obj1, obj2)); // true

let obj3 = { a: 1, b: { c: 4 } };
console.log(deepEqual(obj1, obj3)); // false

let arr1 = [1, 2, { a: 1 }];
let arr2 = [1, 2, { a: 1 }];
console.log(deepEqual(arr1, arr2)); // true

3. 使用 Lodash 的 _.isEqual:

Lodash 是一个流行的 JavaScript 实用工具库,提供了一个 _.isEqual 函数,可以进行深度比较。它处理各种边缘情况,包括循环引用。

const _ = require('lodash');

let obj1 = { a: 1, b: { c: 3 } };
let obj2 = { a: 1, b: { c: 3 } };
console.log(_.isEqual(obj1, obj2)); // true

let obj3 = { a: 1, b: { c: 4 } };
console.log(_.isEqual(obj1, obj3)); // false

// 处理循环引用
let obj4 = {};
obj4.a = obj4;
let obj5 = {};
obj5.a = obj5;
console.log(_.isEqual(obj4, obj5)); // true

选择哪种方法?

  • 对于简单的对象比较,JSON.stringify 可能足够。
  • 对于更复杂的情况,递归方法提供更大的控制力和灵活性。
  • 对于需要处理循环引用或其他边缘情况的生产
posted @   王铁柱6  阅读(60)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 零经验选手,Compose 一天开发一款小游戏!
· 一起来玩mcp_server_sqlite,让AI帮你做增删改查!!
点击右上角即可分享
微信分享提示