打字稿 - 克隆对象
我有一个超类,它是许多子类的父(实体
)( Customer
,产品
, ProductCategory
...)
I have a super class that is the parent (Entity
) for many subclass (Customer
, Product
, ProductCategory
...)
我期待动态克隆包含Typescript中不同子对象的对象。
I'm looking to clone dynamically an object that contains different sub objects in Typescript.
例如:客户
有不同的产品
谁拥有 ProductCategory
In example : a Customer
that has different Product
who has a ProductCategory
var cust:Customer = new Customer ();
cust.name = "someName";
cust.products.push(new Product(someId1));
cust.products.push(new Product(someId2));
为了克隆整个对象树,我在实体中创建了一个函数
In order to clone the whole tree of object I created a function in 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;
}
新
上升当它被转换为javascript时出现以下错误:错误TS2351:不能对类型缺少调用或构造签名的表达式使用new。
The new
rises the following error when it is transpiled to javascript: error TS2351: Cannot use 'new' with an expression whose type lacks a call or construct signature.
虽然脚本有效, 我想摆脱已发现的错误
Although the script works, I would like to get rid of the transpiled error
解决特定问题
您可以使用类型断言告诉编译器您更了解:
Solving The Specific Issue
You can use a type assertion to tell the compiler that you know better:
public clone(): any {
var cloneObj = new (<any>this.constructor());
for (var attribut in this) {
if (typeof this[attribut] === "object") {
cloneObj[attribut] = this.clone();
} else {
cloneObj[attribut] = this[attribut];
}
}
return cloneObj;
}
克隆
请记住,有时候编写自己的映射会更好 - 而不是完全动态。但是,你可以使用一些克隆技巧给你带来不同的效果。
Cloning
Bear in mind that sometimes it is better to write your own mapping - rather than being totally dynamic. However, there are a few "cloning" tricks you can use that give you difference effects.
我将在后面的所有例子中使用以下代码:
I will use the following code for all the subsequent examples:
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:点差
属性: 是
方法:否
深层复制:否
Properties: Yes Methods: No Deep Copy: No
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
Option 2: Object.assign
属性:是
方法:否
深层复制:否
Properties: Yes Methods: No Deep Copy: No
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
Option 3: Object.create
属性:是
方法:是
深层复制:否
Properties: Yes Methods: Yes Deep Copy: No
var clone = Object.create(customer);
alert(clone.name + ' ' + clone.example.type); // David DavidType
alert(clone.greet()); // OK
clone.name = 'Steve';
clone.example.type = 'SteveType';
alert(customer.name + ' ' + customer.example.type); // David 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 = <Customer>deepCopy(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