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

如何深度克隆以Symbol()为键的嵌套对象?

深度克隆含Symbol键的对象的方法

常规的JSON.parse(JSON.stringify())和structuredClone()都会忽略对象的Symbol类型键,要实现包含Symbol键的深度克隆,可以用以下几种方式:

1. 手动递归实现(无依赖)

自己实现克隆逻辑,通过Reflect.ownKeys()获取对象的所有自身属性键(包括Symbol和不可枚举字符串键),同时处理循环引用和属性描述符:

function deepCloneWithSymbol(obj, cache = new WeakMap()) {
  // 处理原始值和null
  if (obj === null || typeof obj !== 'object') {
    return obj;
  }

  // 处理已克隆过的对象(解决循环引用)
  if (cache.has(obj)) {
    return cache.get(obj);
  }

  // 克隆数组
  if (Array.isArray(obj)) {
    const clonedArr = [];
    cache.set(obj, clonedArr);
    return obj.map(item => deepCloneWithSymbol(item, cache));
  }

  // 克隆普通对象,保留原型
  const clonedObj = Object.create(Object.getPrototypeOf(obj));
  cache.set(obj, clonedObj);

  // 获取所有键(含Symbol)
  const allKeys = Reflect.ownKeys(obj);

  allKeys.forEach(key => {
    const propDesc = Object.getOwnPropertyDescriptor(obj, key);
    if (propDesc) {
      // 递归克隆属性值
      propDesc.value = deepCloneWithSymbol(propDesc.value, cache);
      Object.defineProperty(clonedObj, key, propDesc);
    }
  });

  return clonedObj;
}

// 测试示例
const testSym = Symbol('demo');
const nestedSym = Symbol('nested');
const original = {
  [testSym]: 42,
  name: 'foo',
  nested: { [nestedSym]: 'bar' }
};
// 加循环引用测试
original.self = original;

const cloned = deepCloneWithSymbol(original);
console.log(cloned[testSym]); // 输出 42
console.log(cloned.nested[nestedSym]); // 输出 'bar'
console.log(cloned.self === cloned); // 输出 true(正确处理循环引用)
console.log(cloned === original); // 输出 false(确认是深克隆)

这个方法完全自定义,不需要依赖第三方库,同时能完整保留对象的所有属性特性(包括可枚举性、读写权限等)。

2. 使用第三方库(如Lodash)

如果你的项目已经引入Lodash,它的cloneDeep方法原生支持Symbol键的深度克隆,无需额外处理:

const _ = require('lodash');

const testSym = Symbol('demo');
const original = { [testSym]: 42 };
const cloned = _.cloneDeep(original);

console.log(cloned[testSym]); // 输出 42

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 03:15:07