在Angular中深度复制对象

Ank*_*ngh 49 angular

AngularJS必须angular.copy()深度复制对象和数组.

Angular也有类似的东西吗?

Gab*_*ntú 53

您还可以使用:

JSON.parse(JSON.stringify(Object))

如果它在你的范围内,它在每个Angular组件,指令等中,并且它也在每个节点环境中.

除非您有循环引用,否则它应该有效,并且会有效地将您的变量引用与原始对象分离.

  • 另外,如果您使用带有函数(不只是值)的对象文字,它们将被忽略,但是您可以轻松地将Object.assing({},oldObject,JSON.parse(JSON.stringify(oldObject) ))`,这将从对象文字中重新填充您的函数属性,并使用JSON创建深层副本,而与原始副本没有任何关系。 (2认同)
  • 但是要注意,当有一些日期时,这是行不通的。 (2认同)

mar*_*tin 20

这个问题不是重复我如何在角度2中使用angular.copy,因为OP询问深度复制对象.链接的答案建议使用Object.assign(),它不会生成深层副本.

其实用Angular2不使用其他库,例如限制你的jQuery深拷贝与他们的对象$ .clone()函数或lodash_.cloneDeep() .

最常见的图书馆有提供其分型通过分型 CLI工具,所以即使从打字稿transpiling时,你可以无缝地使用任何你想要的.

另请参阅:在JavaScript中深度克隆对象的最有效方法是什么?


And*_*nti 20

另一种选择是实现自己的功能:

/**
 * Returns a deep copy of the object
 */
public static deepCopy(oldObj: any) {
    var newObj = oldObj;
    if (oldObj && typeof oldObj === "object") {
        if (oldObj instanceof Date) {
           return new Date(oldObj.getTime());
        }
        newObj = Object.prototype.toString.call(oldObj) === "[object Array]" ? [] : {};
        for (var i in oldObj) {
            newObj[i] = this.deepCopy(oldObj[i]);
        }
    }
    return newObj;
}
Run Code Online (Sandbox Code Playgroud)


Bog*_*anC 9

你可以deep copy使用lodash的cloneDeep方法在Angular中创建一个对象:

yarn add lodash或安装lodash npm install lodash.

在您的组件中,导入cloneDeep并使用它:

import * as cloneDeep from 'lodash/cloneDeep';
...
clonedObject = cloneDeep(originalObject);
Run Code Online (Sandbox Code Playgroud)

它只为您的构建添加了18kb,非常值得获益.

如果你需要更多地了解为什么使用lodash的cloneDeep,我也在这里写了一篇文章.


Kri*_*u K 5

Create helper class with name deepCopy.ts

/*
* DeepCopy class helps to copy an Original Array or an Object without impacting on original data
*/

export class DeepCopy {

  static copy(data: any) {
    let node;
    if (Array.isArray(data)) {
      node = data.length > 0 ? data.slice(0) : [];
      node.forEach((e, i) => {
        if (
          (typeof e === 'object' && e !== {}) ||
          (Array.isArray(e) && e.length > 0)
        ) {
          node[i] = DeepCopy.copy(e);
        }
      });
    } else if (data && typeof data === 'object') {
      node = data instanceof Date ? data : Object.assign({}, data);
      Object.keys(node).forEach((key) => {
        if (
          (typeof node[key] === 'object' && node[key] !== {}) ||
          (Array.isArray(node[key]) && node[key].length > 0)
        ) {
          node[key] = DeepCopy.copy(node[key]);
        }
      });
    } else {
      node = data;
    }
    return node;
  }
}
Run Code Online (Sandbox Code Playgroud)

在需要的地方导入deepCopy文件,并使用以下代码 DeepCopy.copy(arg); ,这里arg将是您要选择的对象或数组

  • 我不会盲目地复制这个片段。它有效,但有缺陷。在数组和对象断言中存在重复的代码。在该重复代码中,此“e!=={}”将始终为 true,并且由于“typeof [] === 'object'”,OR 管道之后的部分将永远不会按预期工作。这也将简单地复制它遇到的任何日期。该三元组的第一部分看起来像`? 新日期(数据):`。 (5认同)

vp_*_*rth 5

对KrishnamrajuK 的答案进行一些修改

export class DeepCopy {
  static copy(data: any, objMap?: WeakMap<any, any>) {
    if (!objMap) {
      // Map for handle recursive objects
      objMap = new WeakMap();
    }

    // recursion wrapper
    const deeper = value => {
      if (value && typeof value === 'object') {
        return DeepCopy.copy(value, objMap);
      }
      return value;
    };

    // Array value
    if (Array.isArray(data)) return data.map(deeper);

    // Object value
    if (data && typeof data === 'object') {
      // Same object seen earlier
      if (objMap.has(data)) return objMap.get(data);
      // Date object
      if (data instanceof Date) {
        const result = new Date(data.valueOf());
        objMap.set(data, result);
        return result;
      }
      // Use original prototype
      const node = Object.create(Object.getPrototypeOf(data));
      // Save object to map before recursion
      objMap.set(data, node);
      for (const [key, value] of Object.entries(data)) {
        node[key] = deeper(value);
      }
      return node;
    }
    // Scalar value
    return data;
  }
}

Run Code Online (Sandbox Code Playgroud)

  • 这个答案涉及递归对象,这使其成为最佳答案! (2认同)