引用类型数组去重
上一篇文章中我们探讨了使用javascript对只包含原始类型元素的数组进行去重,遗留下一个问题,就是当数组中包含两个“长得一样”的对象的时候,该如何去重?
测试数据
let a = {"a": 1};
let b = {"a": 1};
let c = {"b": 2};
let arr = [a, b, c];
使用set去重是失效的
console.log([...new Set(arr)]); // [ { a: 1 }, { a: 1 }, { b: 2 } ]
实现过程
需要先实现一个判断两个对象是否“长得一样”的函数。
/**
* @description: 检查两个对象 obj1 和 obj2 是否值相等
* @param {*} obj1
* @param {*} obj2
* @return {*}
*/
function checkObj(obj1, obj2) {
// 指向同一内存
if (obj1 === obj2) return true;
let arr1 = Object.keys(obj1),
arr2 = Object.keys(obj2);
// 判断属性值是否相等
if (arr1.length != arr2.length) return false;
for (const k in arr1) {
if (typeof arr1[k] == "object" || typeof arr2[k] == "object") {
if (!checkObj(arr1[k], arr2[k])) return false;
} else if (arr1[k] !== arr2[k]) {
return false;
}
}
return true;
}
在数组原型扩展includesObj 方法,判断数组上是否存在某对象。
/**
* @description: 在数组原型上写方法
* @param {*} itemObj
* @return {*}
*/
Array.prototype.includesObj = function (itemObj) {
let flag = false;
for (let i = 0; i < this.length; i++) {
if (checkObj(this[i], itemObj)) {
flag = true;
break;
}
}
return flag;
};
实现去重函数,遍历输入的数组 nums,对于每个对象,使用 includesObj 方法检查它是否已经存在于 result 中。如果当前对象不在 result 中,则将其添加到 result 中。最终返回 result 数组,即为去重后的对象数组。
/**
* @description: 针对对象数组,且可能出现对象引用的问题
* @param {*} arr
* @return {*}
*/
function uniqSpecial(arr) {
const result = [];
for (let i = 0; i < arr.length; i++) {
// 如果不存在
if (!result.includesObj(arr[i])) result.push(arr[i]);
}
return result;
}
结果测试
console.log(uniqSpecial(arr)); // [ { a: 1 }, { b: 2 } ]