js中判断Object、Array、Function等引用类型对象是否相等


在JavaScript中,直接比较两个引用类型(如Object、Array、Function等)的相等性通常只会检查它们是否是同一个对象的引用,而不是它们的内容是否相等。要比较这些类型的内容是否相等,需要手动实现深度比较的逻辑。

下面是一个简单的函数示例,用于比较两个对象(包括数组)是否深度相等。请注意,这个函数为了简化,没有处理函数类型(Function)的直接比较,因为函数的内容(如闭包内的状态)通常很难或不可能进行精确的比较。


function isDeepEqual(obj1, obj2) {
  // 检查基本类型或相同引用
  if (obj1 === obj2) return true;
  // 检查类型是否相同
  if (typeof obj1 !== typeof obj2) return false;
  // 检查是否为null
  if (obj1 === null || obj2 === null) return false;

  // 处理日期
  if (obj1 instanceof Date && obj2 instanceof Date) {
    return obj1.getTime() === obj2.getTime();
  }

  // 处理数组或对象
  if (typeof obj1 === 'object' || typeof obj1 === 'function') {
    // 获取对象/数组的长度
    const keys1 = Object.keys(obj1);
    const keys2 = Object.keys(obj2);

    // 长度必须相同
    if (keys1.length !== keys2.length) return false;

    // 遍历键
    for (let key of keys1) {
      // 检查键是否存在且值相等
      if (!keys2.includes(key) || !isDeepEqual(obj1[key], obj2[key])) {
        return false;
      }
    }

    return true;
  }

  // 对于Function,这里简单地返回false,因为没有通用的方式来比较它们的内容
  if (typeof obj1 === 'function' || typeof obj2 === 'function') {
    return false;
  }

  // 如果不是上述类型,则视为不相等
  return false;
}

// 示例
const obj1 = { a: 1, b: { c: 2 } };
const obj2 = { a: 1, b: { c: 2 } };
const arr1 = [1, 2, [3, 4]];
const arr2 = [1, 2, [3, 4]];

console.log(isDeepEqual(obj1, obj2)); // true
console.log(isDeepEqual(arr1, arr2)); // true

请注意,上述函数在处理具有循环引用的对象时可能会陷入无限递归。此外,对于特殊对象(如`RegExp`、`Map`、`Set`等),你需要扩展这个函数以支持这些类型的比较。

对于函数(Function)的相等性检查,由于JavaScript中函数是引用类型,并且它们的“内容”可能包括闭包中的状态,因此通常很难或不可能进行精确的比较。在实际应用中,你可能需要根据具体情况来定义函数“相等”的含义,并相应地实现比较逻辑。