Skip to content

数组去重,很多人第一时间想到的是[...new Set(arr)],但是这种方式只能对基本数据类型进行去重。

Set的内部实现中,是使用Object.is()来判断是不是重复

js
Object.is(0, -0); // false
Object.is(NaN, NaN); // true
Object.is({}, {}); // false

所以对于数组去重这件事,还有一个最关键的问题:怎么定义为重复?

在通常的业务代码中,两个空对象{}应该被定义为重复数据才对,此时我们需要加上一个条件:

两个属性相同的对象也认为是重复的

上代码

js
function uniqueArray(arr) {
  const result = [];

  outer: for (const item of arr) {
    for (const r of result) {
      if (equals(item, r)) continue outer;
    }
    result.push(item);
  }

  return result;
}

怎么判断两个数据是否相同?

首先我们需要判断数据是否原始值,也就是基本数据类型,如果是,那么直接用Object.is()去判断即可

js
function isPrimitive(val) {
  return val !== Object(val);
}

TIP

Object传入数组或者对象,会返回原本的数组或对象,传入数字或字符串,则会得到它的包装类

判断两个数据是否相同

js
function equals(value1, value2) {
  if (isPrimitive(value1) || isPrimitive(value2)) {
    return Object.is(value1, value2);
  }

  const entries1 = Object.entries(value1);
  const entries2 = Object.entries(value2);
  if (entries1.length !== entries2.length) return false;

  for (const [key, val] of entries1) {
    // 当此对象的key不存在另一个对象中的时候,直接返回false
    if (!Object.hasOwnProperty(value2, key)) return false;
    // 属性值有可能为对象类型,递归判断
    if (!equals(val, value2[key])) return false;
  }

  return true;
}