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

如何实现可识别键相同但顺序不同对象的memoize缓存函数

问题原因
  • 原生JSON.stringify序列化普通对象时会保留键的定义顺序,两个键完全相同但顺序不同的对象会生成完全不同的序列化结果,导致缓存key不匹配,无法命中缓存。
解决方案

核心思路是实现一个稳定序列化函数,序列化对象时先对键进行排序,保证键序不同但内容相同的对象能生成相同的序列化结果,再替换原有memoize中生成key的逻辑即可。

完整实现代码

// 稳定序列化函数,保证同内容不同键序的对象输出相同结果
const stableStringify = (value) => {
  // 处理基础类型、null、undefined
  if (typeof value !== 'object' || value === null) {
    // 单独处理特殊基础类型,避免序列化结果歧义
    if (value === undefined) return 'undefined'
    if (typeof value === 'number' && isNaN(value)) return 'NaN'
    if (typeof value === 'number' && !isFinite(value)) return value > 0 ? 'Infinity' : '-Infinity'
    return JSON.stringify(value)
  }

  // 处理日期类型
  if (value instanceof Date) {
    return `Date(${value.toISOString()})`
  }

  // 处理正则类型
  if (value instanceof RegExp) {
    return `RegExp(${value.toString()})`
  }

  // 处理数组类型
  if (Array.isArray(value)) {
    return `[${value.map(item => stableStringify(item)).join(',')}]`
  }

  // 处理普通对象:先排序键再序列化
  const sortedKeys = Object.keys(value).sort()
  const objStr = sortedKeys.map(key => {
    return `${stableStringify(key)}:${stableStringify(value[key])}`
  }).join(',')
  return `{${objStr}}`
}

const memoize = fn => {
  const cache = Object.create(null); // 用空对象避免原型链属性干扰

  return (...args) => {
    // 用稳定序列化生成key
    const key = stableStringify(args)
    if (!(key in cache)) {
      cache[key] = fn(...args)
    }
    return cache[key]
  }
}

// 测试代码
const stringifyObj = (obj) => {
   console.log(obj)
   return JSON.stringify(obj)
}

const myMemo = memoize(stringifyObj)

const a = myMemo({ hello: "world", goodnight: "moon" })
const b = myMemo({ goodnight: "moon", hello: "world" })
// 控制台仅打印一次对象,说明缓存命中符合预期
扩展说明
  • 上述实现支持任意数量、任意类型的参数,包括嵌套对象、数组、日期、正则、NaN、Infinity等特殊场景
  • 如果需要处理循环引用的对象,可以在stableStringify中加入WeakSet记录已遍历的对象,避免递归爆栈
  • 如果对性能要求极高,也可以用Map结合自定义哈希逻辑代替字符串key,减少大对象序列化的性能开销

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 09:18:00