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

如何让含私有属性的类实例通过lodash isEqual比较时私有属性不同返回false

解决lodash isEqual无法区分私有属性不同的类实例问题

问题原因

你遇到的问题核心在于JavaScript的私有字段(#开头)是真正的私有,外部代码(包括lodash)无法直接访问这些字段。_.isEqual默认只会比较对象的可枚举公开属性,而你的Bobcat实例没有任何公开属性,所以lodash判定两个实例结构完全一致,返回true,哪怕它们的私有#items内容不同。

解决方案:外部实现自定义比较逻辑

按照要求,我们不在类内部添加任何方法,而是在外部封装一个自定义的比较函数,针对Bobcat实例做特殊处理,同时保留lodash对其他类型的默认比较能力。

思路是:利用Bobcat类提供的公开entries()方法,将私有#items的键值对转换为可比较的数组,再用lodash比较这些数组内容。

const _ = require('lodash')

// 原Bobcat类保持不变
class Bobcat {
  #items;

  constructor() {
    this.#items = new Map()
  }

  set(key, value) {
    return this.#items.set(key, value)
  }

  get(key) {
    return this.#items.get(key)
  }

  has(key) {
    return this.#items.has(key)
  }

  delete(key) {
    return this.#items.delete(key)
  }

  clear() {
    this.#items.clear()
  }

  keys() {
    return this.#items.keys()
  }

  values() {
    return this.#items.values()
  }

  entries() {
    return this.#items.entries()
  }

  forEach(callbackFn, thisArg) {
    return this.#items.forEach(callbackFn, thisArg)
  }

  [Symbol.iterator]() {
    return this.#items[Symbol.iterator]()
  }
}

// 外部自定义比较函数
function customIsEqual(a, b) {
  const isBobcatA = a instanceof Bobcat
  const isBobcatB = b instanceof Bobcat

  // 两个都是Bobcat实例的情况
  if (isBobcatA && isBobcatB) {
    // 把私有Map的键值对转为数组
    const aEntries = Array.from(a.entries())
    const bEntries = Array.from(b.entries())
    // 比较键值对数组,同时保留对实例公开属性的比较(如果后续添加公开属性也能兼容)
    return _.isEqual(aEntries, bEntries) && _.isEqual(_.omit(a, []), _.omit(b, []))
  } 
  // 一个是Bobcat,一个不是,直接不相等
  else if (isBobcatA !== isBobcatB) {
    return false
  }
  // 其他类型用lodash默认逻辑
  return _.isEqual(a, b)
}

// 测试用例
const cat1 = new Bobcat()
cat1.set('a', 1)

const cat2 = new Bobcat()
cat2.set('a', 2)

const cat3 = new Bobcat()
cat3.set('a', 1)

console.log(customIsEqual(cat1, cat2)) // false(符合预期)
console.log(customIsEqual(cat1, cat3)) // true(符合预期)
console.log(customIsEqual({x:1}, {x:1})) // true(不影响其他类型比较)

说明

  • 这个方案完全遵循要求:所有比较逻辑在类外部实现,没有修改Bobcat类的内部代码,也没有添加类内方法或lodash专属的Symbol方法。
  • 利用类本身提供的公开方法(entries())间接获取私有属性的内容,既不破坏封装性,又能实现正确的比较。
  • 保留了lodash对其他类型的默认比较逻辑,不会影响原有代码中对非Bobcat实例的比较。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 07:53:17