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

如何深度克隆带原型链的对象?structuredClone无法实现

如何克隆对象树并保留原型链?

structuredClone确实无法保留对象的原型链,它只会克隆对象的自有数据属性,不会继承原对象的原型方法。就像你给出的示例:

class Some {
  hi() { return 'hi' }
}

const a = new Some()
console.log(a.hi())

const b = structuredClone(a)
console.log(b.hi()) // => TypeError: b.hi is not a function

克隆后的b只是一个普通对象,并非Some类的实例,因此无法调用原型上的hi方法。

下面是几种可以克隆对象树且保留原型链的方案:

1. 手动实现递归克隆函数

这个方法会完整保留原型链,同时递归处理嵌套对象,支持所有自有属性(包括不可枚举属性和Symbol属性):

class Some {
  hi() { return 'hi' }
}

function deepCloneWithPrototype(obj) {
  // 处理null和基本数据类型
  if (obj === null || typeof obj !== 'object') return obj;

  // 创建与原对象原型一致的新对象
  const clonedObj = Object.create(Object.getPrototypeOf(obj));

  // 获取原对象所有自有属性的描述符
  const propertyDescriptors = Object.getOwnPropertyDescriptors(obj);

  // 遍历所有自有属性(包括Symbol)
  for (const key of Reflect.ownKeys(obj)) {
    const descriptor = propertyDescriptors[key];
    // 如果属性值是对象,递归克隆
    if (typeof descriptor.value === 'object' && descriptor.value !== null) {
      descriptor.value = deepCloneWithPrototype(descriptor.value);
    }
    // 将属性描述符赋值给克隆对象
    Object.defineProperty(clonedObj, key, descriptor);
  }

  return clonedObj;
}

// 测试
const a = new Some();
console.log(a.hi()); // 输出: hi

const b = deepCloneWithPrototype(a);
console.log(b.hi()); // 输出: hi
console.log(b instanceof Some); // 输出: true

2. 在自定义类中实现clone方法

如果是你自己定义的类,可以直接在类内部实现克隆逻辑,更灵活地控制克隆过程:

class Some {
  hi() { return 'hi' }

  clone() {
    // 创建当前类的新实例
    const cloned = new this.constructor();
    // 复制自有属性(浅克隆,如需深克隆需递归处理嵌套对象)
    const ownProps = Object.getOwnPropertyDescriptors(this);
    Object.defineProperties(cloned, ownProps);
    
    // 针对嵌套对象的深克隆处理示例
    for (const key of Object.keys(ownProps)) {
      const value = this[key];
      if (typeof value === 'object' && value !== null && !(value instanceof Date)) {
        cloned[key] = deepCloneWithPrototype(value);
      }
    }

    return cloned;
  }
}

// 测试
const a = new Some();
const b = a.clone();
console.log(b.hi()); // 输出: hi
console.log(b instanceof Some); // 输出: true

3. 使用第三方库(可选)

如果项目中已经引入了第三方工具库,比如lodash,它的cloneDeep方法默认会保留对象的原型链:

const b = _.cloneDeep(a);
console.log(b.hi()); // 输出: hi
console.log(b instanceof Some); // 输出: true

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 20:25:16