You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

JavaScript中Set添加相同对象:插入前如何判断对象是否相等?

JavaScript Set 判断对象内容相等的解决方案

JavaScript 的 Set 默认采用引用相等判断元素是否重复——也就是说,只有当两个对象是同一个引用时,Set 才会认为它们是同一个元素。这就是你代码里 person 和 person2 内容完全一致,却能被同时添加进 Set 的原因。

下面是几种在插入对象前检查内容是否“相同”的实用方法:

方法一:用 JSON.stringify 转字符串判断

将对象转为 JSON 字符串,通过判断字符串是否存在来间接检查对象内容是否重复。这种方法简单直观,但有局限性:对象里的函数、undefined、循环引用会被忽略,且键的顺序不同会导致字符串不同(比如 {a:1,b:2} 和 {b:2,a:1} 会被当成不同元素)。

let mySet = new Set();

const person = { name: 'John', age: 21 };
const person2 = { name: 'John', age: 21 };
const person3 = { age: 21, name: 'John' }; // 键顺序不同

// 封装添加逻辑
function addToSet(set, obj) {
  const key = JSON.stringify(obj);
  if (!set.has(key)) {
    set.add(key);
    return true;
  }
  return false;
}

addToSet(mySet, person);
addToSet(mySet, person2); // 内容重复,不会添加
addToSet(mySet, person3); // 键顺序不同,会被添加

console.log([...mySet]);
// 输出: ["{\"name\":\"John\",\"age\":21}","{\"age\":21,\"name\":\"John\"}"]

方法二:自定义对象相等判断函数

自己实现一个对比对象内容的函数,遍历 Set 中已有元素,逐一和待添加对象比较。这种方法可以完全自定义相等规则,比如忽略键顺序、只对比特定字段等。

let mySet = new Set();

const person = { name: 'John', age: 21 };
const person2 = { name: 'John', age: 21 };
const person3 = { name: 'John', age: 22 };

// 自定义内容相等判断函数
function isObjectEqual(objA, objB) {
  if (objA === objB) return true; // 引用相同直接返回true
  const keysA = Object.keys(objA);
  const keysB = Object.keys(objB);
  if (keysA.length !== keysB.length) return false; // 键数量不同直接排除
  // 遍历所有键,对比值
  for (const key of keysA) {
    if (objA[key] !== objB[key]) return false;
  }
  return true;
}

// 封装添加逻辑
function addToSet(set, obj) {
  for (const item of set) {
    if (isObjectEqual(item, obj)) {
      return false; // 已存在内容相同的对象
    }
  }
  set.add(obj);
  return true;
}

addToSet(mySet, person);
addToSet(mySet, person2); // 内容重复,不会添加
addToSet(mySet, person3); // 内容不同,会被添加

console.log(JSON.stringify([...mySet]));
// 输出: [{"name":"John","age":21},{"name":"John","age":22}]

方法三:自定义哈希函数生成唯一标识

通过对象的属性生成一个稳定的哈希字符串(比如先排序键再拼接),这样可以避免 JSON.stringify 对键顺序敏感的问题,同时更灵活地控制哈希规则。

let mySet = new Set();

const person = { name: 'John', age: 21 };
const person2 = { name: 'John', age: 21 };
const person3 = { age: 21, name: 'John' }; // 键顺序不同

// 生成稳定的对象哈希值
function getObjectHash(obj) {
  // 先对键排序,确保键顺序不影响哈希结果
  const sortedKeys = Object.keys(obj).sort();
  // 拼接键和值的字符串
  return sortedKeys.map(key => `${key}:${JSON.stringify(obj[key])}`).join('|');
}

// 封装添加逻辑
function addToSet(set, obj) {
  const hash = getObjectHash(obj);
  if (!set.has(hash)) {
    set.add(hash);
    return true;
  }
  return false;
}

addToSet(mySet, person);
addToSet(mySet, person2); // 哈希相同,不会添加
addToSet(mySet, person3); // 哈希相同,不会添加

console.log([...mySet]);
// 输出: ["age:21|name:\"John\""]

选择建议

  • 若对象结构简单、键顺序固定,优先用 JSON.stringify 方法,代码最简洁。
  • 若需要自定义相等规则(比如只对比部分字段、忽略嵌套对象差异),用 自定义相等判断函数。
  • 若要避免键顺序影响判断,用 自定义哈希函数 方法。

内容的提问来源于stack exchange,提问作者asfafafags

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.19 20:05:28