我有一个超类,它是Entity许多子类(Customer,,Product… )的父类( ProductCategory)
Entity
Customer
Product
ProductCategory
我正在寻找动态克隆一个包含 Typescript 中不同子对象的对象。
例如:一个Customer有不同Product的谁有一个ProductCategory
var cust:Customer = new Customer (); cust.name = "someName"; cust.products.push(new Product(someId1)); cust.products.push(new Product(someId2));
为了克隆整个对象树,我在Entity
public clone():any { var cloneObj = new this.constructor(); for (var attribut in this) { if(typeof this[attribut] === "object"){ cloneObj[attribut] = this.clone(); } else { cloneObj[attribut] = this[attribut]; } } return cloneObj; }
new转译为 javascript 时出现以下错误:error TS2351: Cannot use 'new' with an expression whose type lacks a call or construct signature.
new
error TS2351: Cannot use 'new' with an expression whose type lacks a call or construct signature.
虽然脚本有效, 但我想摆脱编译错误
您可以使用类型断言告诉编译器您更了解:
public clone(): any { var cloneObj = new (this.constructor() as any); for (var attribut in this) { if (typeof this[attribut] === "object") { cloneObj[attribut] = this[attribut].clone(); } else { cloneObj[attribut] = this[attribut]; } } return cloneObj; }
截至 2022 年,有一项提议允许structuredClone深度复制多种类型。
structuredClone
const copy = structuredClone(value)
你可以在什么样的东西上使用它有一些限制。
请记住,有时最好编写自己的映射 - 而不是完全动态的。但是,您可以使用一些“克隆”技巧来获得不同的效果。
我将在所有后续示例中使用以下代码:
class Example { constructor(public type: string) { } } class Customer { constructor(public name: string, public example: Example) { } greet() { return 'Hello ' + this.name; } } var customer = new Customer('David', new Example('DavidType'));
选项 1:传播
属性: 是 方法:否 深拷贝:否
var clone = { ...customer }; alert(clone.name + ' ' + clone.example.type); // David DavidType //alert(clone.greet()); // Not OK clone.name = 'Steve'; clone.example.type = 'SteveType'; alert(customer.name + ' ' + customer.example.type); // David SteveType
选项 2:Object.assign
var clone = Object.assign({}, customer); alert(clone.name + ' ' + clone.example.type); // David DavidType alert(clone.greet()); // Not OK, although compiler won't spot it clone.name = 'Steve'; clone.example.type = 'SteveType'; alert(customer.name + ' ' + customer.example.type); // David SteveType
选项 3:Object.create
属性: 继承 方法: 继承 深层复制: 浅继承 (深层更改影响原始和克隆)
var clone = Object.create(customer); alert(clone.name + ' ' + clone.example.type); // David DavidType alert(clone.greet()); // OK customer.name = 'Misha'; customer.example = new Example("MishaType"); // clone sees changes to original alert(clone.name + ' ' + clone.example.type); // Misha MishaType clone.name = 'Steve'; clone.example.type = 'SteveType'; // original sees changes to clone alert(customer.name + ' ' + customer.example.type); // Misha SteveType
选项 4:深度复制功能
属性: 是 方法:否 深拷贝: 是
function deepCopy(obj) { var copy; // Handle the 3 simple types, and null or undefined if (null == obj || "object" != typeof obj) return obj; // Handle Date if (obj instanceof Date) { copy = new Date(); copy.setTime(obj.getTime()); return copy; } // Handle Array if (obj instanceof Array) { copy = []; for (var i = 0, len = obj.length; i < len; i++) { copy[i] = deepCopy(obj[i]); } return copy; } // Handle Object if (obj instanceof Object) { copy = {}; for (var attr in obj) { if (obj.hasOwnProperty(attr)) copy[attr] = deepCopy(obj[attr]); } return copy; } throw new Error("Unable to copy obj! Its type isn't supported."); } var clone = deepCopy(customer) as Customer; alert(clone.name + ' ' + clone.example.type); // David DavidType // alert(clone.greet()); // Not OK - not really a customer clone.name = 'Steve'; clone.example.type = 'SteveType'; alert(customer.name + ' ' + customer.example.type); // David DavidType