克隆对象

我有一个超类,它是许多子类( CustomerProductProductCategory ...)的父类( Entity

我正在动态克隆包含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;
}

当它被转换为javascript时, new了以下错误: error TS2351: Cannot use 'new' with an expression whose type lacks a call or construct signature.

虽然脚本有效,但我想摆脱转译错误


解决具体问题

你可以使用类型断言来告诉编译器你更清楚:

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;
}

克隆

请记住,有时最好编写自己的映射 - 而不是完全动态的。 但是,您可以使用一些“克隆”技巧,这些技巧会带来不同的效果。

我将对以下所有示例使用以下代码:

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

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

1.使用扩展运算符

const obj1 = { param: "value" };
const obj2 = { ...obj1 };

Spread运算符将从obj1中获取所有字段并将其传播到obj2上。 在结果中,您将得到具有新参考的新对象,并且与原始对象具有相同的字段。

记住它是浅拷贝,这意味着如果对象被嵌套,那么它的嵌套复合参数将通过相同的引用存在于新对象中。

2.Object.assign()

const obj1={ param: "value" };
const obj2:any = Object.assign({}, obj1);

Object.assign创建实际副本,但只有自己的属性,所以原型中的属性不会存在于复制的对象中。 这也是浅拷贝。


3.Object.create()

const obj1={ param: "value" };
const obj2:any = Object.create(obj1);

Object.create 不是在做真正的克隆 ,而是从原型创建对象。 因此,如果对象应克隆主类型属性,请使用它,因为主类型属性分配不是通过引用完成的。

Object.create的使用是在原型中声明的任何函数都可以在我们新创建的对象中使用。


几乎没有关于浅拷贝的事情

浅拷贝将旧对象的所有字段放入新对象中,但这也意味着如果原始对象具有组合类型字段(对象,数组等),则这些字段将放入具有相同引用的新对象中。 原始对象中的这种字段的突变将体现在新对象中。

它可能看起来像一个陷阱,但是当整个复杂对象需要被复制的时候真的很难。 浅拷贝将重新使用大部分内存,这意味着与深拷贝相比,它非常便宜。


深层复制

Spread运算符可以方便地进行深度复制。

const obj1 = { param: "value", complex: { name: "John"}}
const obj2 = { ...obj1, complex: {...obj1.complex}};

以上代码创建了obj1的深层副本。 复合字段“复杂”也被复制到obj2中。 突变字段“复杂”不会反映副本。


使用TypeScript 2.1中引入的“Object Spread”很容易获得浅拷贝

这个TypeScript: let copy = { ...original };

产生这个JavaScript:

var __assign = (this && this.__assign) || Object.assign || function(t) {
    for (var s, i = 1, n = arguments.length; i < n; i++) {
        s = arguments[i];
        for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
            t[p] = s[p];
    }
    return t;
};
var copy = __assign({}, original);

https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-1.html

链接地址: http://www.djcxy.com/p/40681.html

上一篇: cloning object

下一篇: What's alternative to angular.copy in Angular