递归比较
- 原理:通过递归遍历对象或数组的所有属性和元素,对每个属性或元素进行逐一比较,直到比较完所有层级的内容。
- 示例:
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 {
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;
}
}
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
JSON序列化比较
- 原理:先将对象或数组转换为JSON字符串,然后比较这两个JSON字符串是否相等。如果相等,则说明两个对象或数组的内容在结构和值上是相同的。
- 示例:
function jsonDeepEqual(obj1, obj2) {
return JSON.stringify(obj1) === JSON.stringify(obj2);
}
let obj1 = {
name: 'Alice', age: 25, hobbies: ['reading', 'swimming'] };
let obj2 = {
name: 'Alice', age: 25, hobbies: ['reading', 'swimming'] };
console.log(jsonDeepEqual(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(jsonDeepEqual(obj3, obj4)); // true
不过需要注意的是,JSON序列化比较要求对象的属性值必须是能够被JSON序列化的数据类型,如函数、正则表达式等特殊类型在序列化时会丢失信息,导致比较结果不准确。
lodash库的_.isEqual方法
- 原理:lodash是一个常用的JavaScript工具库,其中的
_.isEqual
方法实现了深度比较的功能。它能够递归地比较对象、数组以及各种数据类型的差异,并且能够处理循环引用等复杂情况。 - 示例:
首先需要安装lodash库,然后可以这样使用:
const _ = require('lodash');
let obj1 = {
name: 'Alice', age: 25, hobbies: ['reading', 'swimming'] };
let obj2 = {
name: 'Alice', age: 25, hobbies: ['reading', 'swimming'] };
console.log(_.isEqual(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(_.isEqual(obj3, obj4)); // true
自定义深度比较函数
- 原理:根据具体的业务需求和对象结构,编写自定义的深度比较函数,在函数中明确指定比较的规则和逻辑,对对象的各个属性和嵌套层次进行细致的比较。
- 示例:
function customDeepEqual(obj1, obj2) {
// 比较对象的类型是否相同
if (Object.prototype.toString.call(obj1)!== Object.prototype.toString.call(obj2)) {
return false;
}
if (typeof obj1 === 'object' && obj1!== null) {
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)) {
return false;
}
if (typeof obj1[key] === 'object' && obj1[key]!== null) {
if (!customDeepEqual(obj1[key], obj2[key])) {
return false;
}
} else {
if (obj1[key]!== obj2[key]) {
return false;
}
}
}
}
return true;
}
let obj1 = {
name: 'Alice', age: 25, hobbies: ['reading', 'swimming'] };
let obj2 = {
name: 'Alice', age: 25, hobbies: ['reading', 'swimming'] };
console.log(customDeepEqual(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(customDeepEqual(obj3, obj4)); // true
这些深比较的方法各有优缺点,在实际应用中,可以根据具体的场景和需求选择合适的方法来进行深度比较。递归比较方法较为灵活但需要自己处理各种边界情况;JSON序列化比较简单直接但对数据类型有一定限制;使用lodash库的 _.isEqual
方法方便快捷且功能强大,但需要引入额外的库;自定义深度比较函数则可以根据特定的业务逻辑进行精确的比较。