Deep copying objects in Angular

前端 未结 9 2168
悲&欢浪女
悲&欢浪女 2020-12-01 08:58

AngularJS has angular.copy() to deep copy objects and arrays.

Does Angular also have something like that?

相关标签:
9条回答
  • 2020-12-01 09:16
    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;
      }
    }
    

    Import deepCopy file where ever you required and use as below code DeepCopy.copy(arg); , Here arg would either object or array which you want

    0 讨论(0)
  • 2020-12-01 09:18

    This question isn't a duplicate of How can I use angular.copy in angular 2 because the OP is asking about deep copying objects. The linked answer recommends Object.assign() which doesn't make a deep copy.

    Actually, using Angular2 doesn't restrict you from using other libraries like jQuery for deep copying objects with their $.clone() function or lodash with _.cloneDeep().

    The most common libraries have their typings available via typings CLI tools so even when transpiling from TypeScript you can seamlessly use anything you want.

    Also see: What is the most efficient way to deep clone an object in JavaScript?

    0 讨论(0)
  • 2020-12-01 09:19

    Some modifications for KrishnamrajuK's answer

    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;
      }
    }
    
    
    0 讨论(0)
  • 2020-12-01 09:31

    I have created a very simple function in typescript which accepts all possible inputs and gives the deep cloned copy of that object.

    Hope it will help somebody.

      public deepCopy(obj) {
    
        var clonedObject: any;
    
        if (obj instanceof Array) {
            var itemArray = Object.assign([], obj);
            clonedObject = itemArray;
    
            for (var j = 0; j < clonedObject.length; j++) {
                clonedObject[j] = this.deepCopy(clonedObject[j]);
            }
    
            return clonedObject;
        }
        else if (typeof obj === 'number' || typeof obj == 'string') {
            return obj
        }
        else {
    
    
            var item = Object.assign({}, obj);
            clonedObject = item;
    
            let allKeys = Object.keys(clonedObject);
    
            for (var i = 0; i < allKeys.length; i++) {
                if (clonedObject[allKeys[i]] instanceof Array) {
                    //If the calue is Array
                    clonedObject[allKeys[i]] = this.deepCopy(clonedObject[allKeys[i]]);
                }
                else if (clonedObject[allKeys[i]] instanceof Date) {
                    clonedObject[allKeys[i]] = new Date(clonedObject[allKeys[i]].valueOf());
                }
                else if (clonedObject[allKeys[i]] instanceof Object){
                    //if the value is JOBJECT.
                    clonedObject[allKeys[i]] = this.deepCopy(clonedObject[allKeys[i]]);
                }
            }
            return clonedObject;
        }
    
    
    }
    
    0 讨论(0)
  • 2020-12-01 09:34

    Another option is to implement your own function:

    /**
     * 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;
    }
    
    0 讨论(0)
  • 2020-12-01 09:34

    You can deep copy an object in Angular by using lodash's cloneDeep method:

    Install lodash with yarn add lodash or npm install lodash.

    In your component, import cloneDeep and use it:

    import * as cloneDeep from 'lodash/cloneDeep';
    ...
    clonedObject = cloneDeep(originalObject);
    

    It's only 18kb added to your build, well worth for the benefits.

    I've also written an article here, if you need more insight on why using lodash's cloneDeep.

    0 讨论(0)
提交回复
热议问题