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

如何实现两个同键JS对象对比,返回formData中与initialValues值不同的键值对?

变更值对比实现方案

基础浅比较(适配当前示例场景)

你当前的示例里所有字段值都是字符串这类基本类型,不需要复杂逻辑,直接做严格相等对比就行:
实现思路:

  • 以参照对象initialValues的键集合作为遍历范围,避免纳入formData里独有的无参照字段
  • 逐个对比同名字段两边的值,只要不相等,就把formData里对应的键值对收集到最终结果里

可直接运行的示例代码:

const getChangedValues = (initialValues, formData) => {
  return Object.keys(initialValues).reduce((changed, key) => {
    // 同键值不匹配就收集formData的对应值
    if (formData[key] !== initialValues[key]) {
      changed[key] = formData[key]
    }
    return changed
  }, {})
}

// 对应你的测试用例
const initialValues = { name: "Robert Terrell", email: "billy@gmail.com" }
const formData = { name: 'New Name', email: 'new email' }
console.log(getChangedValues(initialValues, formData))
// 输出结果:{ name: 'New Name', email: 'new email' }

支持深度对比的增强实现

如果你的表单字段里有嵌套对象、数组、日期这类引用类型的值,直接用!==对比会失效——因为两个内容完全一样的对象,只要引用地址不同就会被判定为不相等。这个时候就需要递归逐层对比内容:
实现逻辑:

  • 基本类型 的值直接做严格相等对比
  • 特殊引用类型(日期、正则)提取实际内容做对比
  • 普通对象、数组类型,递归遍历内部键值,直到对比到最内层的基本类型值
  • 只有递归判定内容真的有差异,才把对应字段纳入结果集合

简化版深度对比实现代码:

// 深度相等判断工具
const isDeepEqual = (valA, valB) => {
  // 同值/同引用直接判定相等
  if (Object.is(valA, valB)) return true
  // 任意一侧不是引用类型、或者为null,直接判定不等
  if (typeof valA !== 'object' || valA === null || typeof valB !== 'object' || valB === null) {
    return false
  }
  // 处理日期类型,对比时间戳
  if (valA instanceof Date && valB instanceof Date) {
    return valA.getTime() === valB.getTime()
  }
  // 处理正则类型,对比序列化后的规则内容
  if (valA instanceof RegExp && valB instanceof RegExp) {
    return valA.toString() === valB.toString()
  }
  // 两侧原型不一致(比如一侧是数组一侧是普通对象)直接判定不等
  if (Object.getPrototypeOf(valA) !== Object.getPrototypeOf(valB)) return false

  const keysA = Object.keys(valA)
  const keysB = Object.keys(valB)
  // 键数量不一致直接判定不等
  if (keysA.length !== keysB.length) return false

  // 递归对比每一个嵌套键值
  return keysA.every(key => isDeepEqual(valA[key], valB[key]))
}

// 收集深度变更值的方法
const getDeepChangedValues = (initialValues, formData) => {
  return Object.keys(initialValues).reduce((changed, key) => {
    // 用深度相等判断替换基础对比的严格不等
    if (!isDeepEqual(formData[key], initialValues[key])) {
      changed[key] = formData[key]
    }
    return changed
  }, {})
}

实际使用注意点

  • 遍历范围必须以initialValues的键为基准,不要遍历formData的键,否则会把formData里新增的无参照字段错误判定为变更值
  • 优先根据业务场景选择对比方案:全基本类型字段的表单直接用浅比较,性能更高,不要一开始就上递归逻辑
  • 如果业务里有循环引用的对象,需要额外加一层遍历过的对象缓存,避免递归进入死循环

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.29 10:06:07