如何判断两个引用类型是否相等?

简介: 【10月更文挑战第29天】

在JavaScript中,判断两个引用类型是否相等不能直接使用 ===== 运算符,因为这两个运算符比较的是对象的引用地址而非内容。

浅比较

  • 遍历对象属性:对于普通对象,可以遍历其中一个对象的所有属性,然后检查另一个对象是否具有相同的属性且属性值相等。
function shallowEqual(obj1, obj2) {
   
  if (obj1 === obj2) {
   
    return true;
  }

  if (typeof obj1!== 'object' || obj1 === null || typeof obj2!== 'object' || obj2 === null) {
   
    return false;
  }

  const keys1 = Object.keys(obj1);
  const keys2 = Object.keys(obj2);

  if (keys1.length!== keys2.length) {
   
    return false;
  }

  for (let key of keys1) {
   
    if (!obj2.hasOwnProperty(key) || obj1[key]!== obj2[key]) {
   
      return false;
    }
  }

  return true;
}

let obj1 = {
    name: 'Alice', age: 25 };
let obj2 = {
    name: 'Alice', age: 25 };

console.log(shallowEqual(obj1, obj2)); // true

let obj3 = {
    name: 'Alice', age: 25, hobbies: ['reading', 'swimming'] };
let obj4 = {
    name: 'Alice', age: 25, hobbies: ['reading', 'swimming'] };

console.log(shallowEqual(obj3, obj4)); // true

这种方法对于简单的对象结构可以有效地判断两个对象是否相等,但对于嵌套的对象或数组,只会比较第一层的属性和值。

深比较

  • 递归比较对象和数组:如果对象或数组中包含嵌套的引用类型,需要使用递归的方式进行深度比较。
function deepEqual(obj1, obj2) {
   
  if (obj1 === obj2) {
   
    return true;
  }

  if (typeof obj1!== 'object' || obj1 === null || typeof obj2!== 'object' || obj2 === null) {
   
    return false;
  }

  if (Array.isArray(obj1) && Array.isArray(obj2)) {
   
    if (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 if (typeof obj1 === 'object' && typeof obj2 === 'object') {
   
    const keys1 = Object.keys(obj1);
    const keys2 = Object.keys(obj2);

    if (keys1.length!== keys2.length) {
   
      return false;
    }

    for (let key of keys1) {
   
      if (!obj2.hasOwnProperty(key) ||!deepEqual(obj1[key], obj2[key])) {
   
        return false;
      }
    }

    return true;
  } else {
   
    return false;
  }
}

let obj1 = {
    name: 'Alice', age: 25, hobbies: ['reading', 'swimming'] };
let obj2 = {
    name: 'Alice', age: 25, hobbies: ['reading', 'swimming'] };

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

let obj3 = {
    name: 'Alice', age: 25, details: {
    city: 'New York' } };
let obj4 = {
    name: 'Alice', age: 25, details: {
    city: 'New York' } };

console.log(deepEqual(obj3, obj4)); // true

这种方法会递归地比较对象和数组的所有嵌套层次,确保所有属性和值都相等时才返回 true

JSON序列化比较

  • 将对象转换为JSON字符串:可以先将两个对象转换为JSON字符串,然后比较这两个字符串是否相等。
function jsonEqual(obj1, obj2) {
   
  return JSON.stringify(obj1) === JSON.stringify(obj2);
}

let obj1 = {
    name: 'Alice', age: 25 };
let obj2 = {
    name: 'Alice', age: 25 };

console.log(jsonEqual(obj1, obj2)); // true

let obj3 = {
    name: 'Alice', age: 25, hobbies: ['reading', 'swimming'] };
let obj4 = {
    name: 'Alice', age: 25, hobbies: ['reading', 'swimming'] };

console.log(jsonEqual(obj3, obj4)); // true

这种方法简单直接,但需要注意的是,它要求对象的属性值必须是能够被JSON序列化的数据类型,否则会导致比较结果不准确。

自定义比较函数

  • 根据特定规则比较:根据对象的具体结构和业务需求,编写自定义的比较函数。例如,对于具有特定属性和比较规则的对象,可以在函数中明确指定比较的条件和逻辑。
function customEqual(obj1, obj2) {
   
  if (obj1 === obj2) {
   
    return true;
  }

  if (obj1 instanceof Date && obj2 instanceof Date) {
   
    return obj1.getTime() === obj2.getTime();
  }

  if (typeof obj1 === 'function' && typeof obj2 === 'function') {
   
    return obj1.toString() === obj2.toString();
  }

  // 根据具体对象的属性和比较规则进行自定义比较
  if (obj1.hasOwnProperty('id') && obj2.hasOwnProperty('id')) {
   
    return obj1.id === obj2.id;
  }

  return false;
}

let date1 = new Date('2024-01-01');
let date2 = new Date('2024-01-01');

console.log(customEqual(date1, date2)); // true

let func1 = function () {
    console.log('Hello'); };
let func2 = function () {
    console.log('Hello'); };

console.log(customEqual(func1, func2)); // true

let obj1 = {
    id: 1, name: 'Alice' };
let obj2 = {
    id: 1, name: 'Bob' };

console.log(customEqual(obj1, obj2)); // true

这种方法灵活性最高,但需要根据具体的对象类型和比较要求来仔细编写比较逻辑。

在实际应用中,需要根据具体的场景和对象的特点选择合适的比较方法来判断两个引用类型是否相等。

相关文章
|
1月前
|
存储 JavaScript 前端开发
引用类型的赋值操作和比较方式是怎样的?
【10月更文挑战第29天】引用类型的赋值操作和比较方式的特点决定了在处理引用类型数据时需要特别注意对象的引用关系,以避免因共享引用而导致的数据不一致等问题。
|
5月前
|
Java
指针赋值的几种方法
指针赋值的几种方法
判断变量是否为数组的几种方法
判断变量是否为数组的几种方法
165 0
|
7月前
通过c字符串对拷贝构造和赋值构造进行了解
通过c字符串对拷贝构造和赋值构造进行了解
57 0
|
Java
Java方法的重载、可变个数形参、方法参数的值传递机制
Java方法的重载、可变个数形参、方法参数的值传递机制
104 0
一个等号是赋值。两个等号是判断
一个等号是赋值。两个等号是判断
116 0
一个等号是赋值。两个等号是判断
|
C++
使用C++模板判断是否基本类型
使用C++模板判断是否基本类型
221 0
|
JSON 数据格式
如何判断两个对象/数组相等
如何判断两个对象/数组相等
|
C++
C++ 数组 指针 引用类型的解释及使用
C++ 数组 指针 引用类型的解释及使用
154 0
|
编译器 C++
C++赋值运算符要返回*this的引用
C++赋值运算符要返回*this的引用
255 0