如何在JavaScript父类中实现可继承的类实例半深复制方法?
JavaScript类继承中实现通用半深复制方法
要实现父类定义copy方法,所有子类继承后能返回自身类型的实例,同时完成“半深复制”(创建新实例+浅复制属性),可以通过以下方式实现:
核心思路
利用实例的this.constructor属性动态获取当前调用者的构造函数(父类或子类),创建对应类型的新实例后,将原实例的属性浅复制到新实例上。
完整代码实现
class Parent { constructor(data) { this.data = data; this.commonProperty = "parent-shared"; } copy() { // 获取当前实例的构造函数(可能是Parent/Child1/Child2) const CurrentConstructor = this.constructor; // 创建对应类型的新实例 const copyInstance = new CurrentConstructor(); // 浅复制原实例的所有可枚举自有属性到新实例 Object.assign(copyInstance, this); return copyInstance; } } // 子类示例 class Child1 extends Parent { constructor(data) { super(data); this.child1Property = "child1-unique"; } } class Child2 extends Parent { constructor(data) { super(data); this.child2Property = "child2-unique"; } }
测试验证
// 测试父类复制 const parent = new Parent([1, 2, 3]); const parentCopy = parent.copy(); console.log(parentCopy instanceof Parent); // 输出: true console.log(parentCopy.data === parent.data); // 输出: true(属性浅复制,引用类型共享引用) console.log(parentCopy.commonProperty === parent.commonProperty); // 输出: true // 测试Child1复制 const child1 = new Child1([4, 5, 6]); const child1Copy = child1.copy(); console.log(child1Copy instanceof Child1); // 输出: true console.log(child1Copy.child1Property); // 输出: "child1-unique" // 测试Child2复制 const child2 = new Child2([7, 8, 9]); const child2Copy = child2.copy(); console.log(child2Copy instanceof Child2); // 输出: true console.log(child2Copy.child2Property); // 输出: "child2-unique"
扩展说明
1. 复制不可枚举属性
如果需要复制实例的不可枚举自有属性,可以替换Object.assign为Object.getOwnPropertyDescriptors和Object.defineProperties:
copy() { const CurrentConstructor = this.constructor; const copyInstance = new CurrentConstructor(); // 获取原实例的所有自有属性描述符(包括不可枚举) const propDescriptors = Object.getOwnPropertyDescriptors(this); // 将属性描述符应用到新实例 Object.defineProperties(copyInstance, propDescriptors); return copyInstance; }
2. 构造函数需必填参数的场景
如果类的构造函数要求必须传入参数,直接new CurrentConstructor()会导致实例初始化异常。这种情况下可以在构造函数中保存参数,复制时传递:
class Parent { constructor(data) { // 保存构造参数到实例 this._constructorArgs = [data]; this.data = data; } copy() { const CurrentConstructor = this.constructor; // 传递保存的构造参数创建实例 return new CurrentConstructor(...this._constructorArgs); } }
这种方式需要所有子类遵循“保存构造参数到_constructorArgs”的约定,确保复制时能正确初始化实例。
内容的提问来源于stack exchange,提问作者Nick
相关产品推荐
相关产品推荐

