javascript Set对象是什么_如何去除数组重复项?

Set是ES6引入的唯一值集合,存储值唯一且不强制类型转换,5和"5"视为不同;去重数组用[...new Set(arr)],但对象需手动按字段处理,NaN和+0/-0在Set中自动去重。

Set 是什么:JavaScript 里的唯一值集合

Set 是 ES6 引入的内置构造函数,它存储的值必须是唯一的(重复值会被自动忽略),且不强制类型转换——5"5" 被视为不同值。
它不是数组,没有索引,不能用 [0] 取值;也不支持 map/filter 等数组方法,但提供 .add().has().size.values() 等接口。

用 Set 去重数组:最简写法与注意事项

把数组转成 Set,再转回数组,是最常见的去重方式:

const arr = [1, 2, 2, 3, "3", 4, 4, 5];
const uniqueArr = [...new Set(arr)]; // [1, 2, 3, "3", 4, 5]

这个写法简洁,但要注意以下几点:

  • [...new Set(arr)] 依赖展开运算符,IE 不支持;如需兼容旧环境,得用 Array.from(new Set(arr))
  • Set 对象只对原始值(string/number/boolean/symbol/null/undefined)做严格相等判断;{a:1}{a:1} 仍被视为两个不同对象,不会去重
  • 去重后顺序保持原数组首次出现的顺序,这点比用 filter() + indexOf() 更可靠

对象数组去重不能直接用 Set?得手动处理

Set 对对象引用敏感,两个结构相同但内存地址不同的对象,new Set([{a:1}, {a:1}]) 会保留两者。要去重对象数组,得先提取唯一标识(如 id 字段)或序列化比较:

const users = [{id: 1, name: "Alice"}, {id: 2, name: "Bob"}, {id: 1, name: "Alice"}];
const seen = new Set();
const uniqueUsers = users.filter(item => {
  if (seen.has(item.id)) return false;
  seen.add(item.id);
  return true;
}); // [{id: 1, name: "Alice"}, {id: 2, name: "Bob"}]

常见错误是直接写 [...new Set(users)],结果毫无变化——因为每个对象都是新引用。

性能和边界情况:大数组、NaN、+0/-0

Set 去重平均时间复杂度是 O(n),比双层循环的 O(n²) 快得多,适合几千项以内的数组。但仍有几个容易被忽略的细节:

  • NaN 在 Set 中只算一个值:new Set([NaN, NaN]).size === 1,这是它比 === 更“合理”的地方
  • +0-0 在 Set 中被视为相等:new Set([+0, -0]).size === 1,这与 Object.is() 一致,但不同于 ===
  • 如果数组含大量嵌套对象或函数,Set 本身不报错,但去重无效——得确认你真正想比较的是什么

别指望 Set 自动理解业务语义;它只认内存引用或原始值相等性。对象去重、深比较、按字段筛选,都得自己加逻辑。