कोणीय में कोणीय.कॉपी का क्या विकल्प है


136

मैं किसी ऑब्जेक्ट की प्रतिलिपि कैसे बना सकता हूं और इसका संदर्भ कोणीय में खो सकता हूं?

AngularJS के साथ, मैं उपयोग कर सकता हूं angular.copy(object), लेकिन मुझे Angular में इसका उपयोग करने में कुछ त्रुटि हो रही है।

अपवाद: संदर्भ: angularपरिभाषित नहीं है


इस समाधान की जाँच करें इससे मदद मिल सकती है: लिंक
नोरडाइन अलौने

कई स्थितियों में, आप उपयोग करना चाह सकते हैं .copy()लेकिन वास्तव में इसकी आवश्यकता नहीं होगी। विभिन्न AngJS1 परियोजनाओं में मैंने देखा है, यह एक ओवरकिल था, जहां संबंधित उपग्रहों की एक मैनुअल कॉपी एक क्लीनर कोड के लिए बनाई गई होगी। हो सकता है कि यह कोणीय टीम द्वारा इसे लागू न करने के निर्णय का हिस्सा था।
२१

वैसे, संबंधित (और अनुत्तरित भी): stackoverflow.com/questions/41124528/…
phil294

जवाबों:


180

मान लें कि आप ES6 का उपयोग कर रहे हैं, तो आप उपयोग कर सकते हैं var copy = Object.assign({}, original)। आधुनिक ब्राउज़रों में काम करता है; यदि आपको पुराने ब्राउज़र का समर्थन करने की आवश्यकता है तो इस पॉलीफ़िल की जाँच करें

अपडेट करें:

टाइपस्क्रिप्ट 2.1+ के साथ, ES6 शॉर्टहैंड ऑब्जेक्ट स्प्रेड नोटेशन उपलब्ध है:

const copy = { ...original }

75
ध्यान दें कि angular.copy()इसके विपरीत एक गहरी प्रतिलिपि बनाता है Object.assign()। यदि आप डीप कॉपी का उपयोग करना चाहते हैं, तो दर्ज करें _.cloneDeep(value) ।ashashdd
bertrandg

वेबस्टॉर्म में मुझे मिला Unresolved function or method assign(); आईडीई विवरण: वेबस्टॉर्म 2016.2। मैं इसे कैसे हल कर सकता हूं?
मिहई

2
@meorfi पर जाएं File -> Settings -> Languages & Frameworks -> Javascriptऔर सेट Javascript language versionकरें ECMAScript 6.0
सिरी 0 एसपी

@bertrandg _.clone (मान) angular.copy () से भिन्न है, यह नया उदाहरण नहीं बनाएगा, इसलिए _.cloneDeep (मान) के रूप में यह अभी भी एक संदर्भ stackoverflow.com/questions/26411464/…
उत्साह

5
इसके अतिरिक्त, यदि आप किसी सरणी को कॉपी कर रहे हैं, तो उपयोग करें:const copy = [ ...original ]
daleyjem

43

जब तक हमारे पास एक बेहतर समाधान नहीं है, तब तक आप निम्नलिखित का उपयोग कर सकते हैं:

duplicateObject = <YourObjType> JSON.parse(JSON.stringify(originalObject));

संपादित करें: स्पष्टीकरण

कृपया ध्यान दें: उपरोक्त समाधान केवल एक त्वरित-ठीक एक लाइनर होने के लिए था, एक समय पर प्रदान किया गया था जब कोणीय 2 सक्रिय विकास के अधीन था। मेरी आशा थी कि हम अंततः एक समकक्ष प्राप्त कर सकते हैं angular.copy()। इसलिए मैं गहरी-क्लोनिंग लाइब्रेरी लिखना या आयात नहीं करना चाहता था।

इस पद्धति में पार्सिंग डेट प्रॉपर्टीज के साथ भी समस्याएं हैं (यह एक स्ट्रिंग बन जाएगी)।

कृपया इस पद्धति का उपयोग उत्पादन एप्लिकेशन में न करें । इसका प्रयोग केवल अपनी प्रायोगिक परियोजनाओं में करें - जिन्हें आप कोणीय 2 सीखने के लिए कर रहे हैं।


11
यह आपकी तारीखों को बर्बाद करता है और नरक के रूप में धीमा है।
लैंडरवी

5
एक कार्य को करने के लिए पूरी लाइब्रेरी आयात करने में उतना धीमा नहीं है, हालांकि जब तक आप जो कर रहे हैं वह बहुत सरल है ...
इयान बेल्चर

1
यह भयानक है, कभी भी इसका उपयोग न करें
मुराफ सूसली

1
@MurhafSousli कृपया इस उत्तर के संदर्भ को समझने का प्रयास करें। यह तब प्रदान किया गया था जब एंगुलर 2 विकास के अधीन था, और आशा थी कि हम अंततः कोणीय.कोप () फ़ंक्शन के बराबर प्राप्त करेंगे। प्रतीक्षा अवधि को पार करने के लिए, मैंने इस समाधान को एक अस्थायी विकल्प के रूप में रखा, जब तक कि हमारे पास बेहतर समाधान न हो। यह एक-लाइनर है, जिसमें गहरी क्लोनिंग है। यह भयानक है , मैं सहमत हूं ... लेकिन उस समय प्रयोगात्मक संदर्भ को देखते हुए, यह उतना बुरा नहीं है।
मणि

1
@ LazarLjubenović 2018 में निश्चित रूप से यही मामला है और मैं आज पूरी तरह से आपसे सहमत हूं , लेकिन 2016 में वेबपैक में पेड़ हिलना नहीं था इसलिए आप ज्यादातर मामलों में पूरी लाइब्रेरी आयात कर रहे होंगे।
इयान बेल्चर

22

गहरी नकल वस्तुओं के अंदर अंदर नेस्टेड वस्तुओं के लिए विकल्प है जो लॉश के क्लोनडिप विधि का उपयोग करके है।

कोणीय के लिए, आप इसे इस तरह से कर सकते हैं:

के साथ yarn add lodashया स्थापित करेंnpm install lodash

अपने घटक में, cloneDeepइसे आयात और उपयोग करें:

import { cloneDeep } from "lodash";
...
clonedObject = cloneDeep(originalObject);

यह केवल 18kb आपके बिल्ड में जोड़ा गया है, लाभ के लिए अच्छी तरह से लायक है।

मैंने यहां एक लेख भी लिखा है , अगर आपको लॉश के क्लोनडाइप का उपयोग करने के बारे में अधिक जानकारी की आवश्यकता है।


2
"केवल 18kb" को आउटपुट में जोड़ा गया है ताकि वह केवल गहरी कॉपी ऑब्जेक्ट्स में सक्षम हो सके? जावास्क्रिप्ट एक गड़बड़ है।
एंडरजू

आपके संदर्भित लेख को पढ़ने के बाद, मैं इस cloneDeepविधि को एक नई वस्तु को बताता है। यदि हमारे पास पहले से ही एक गंतव्य वस्तु है, तो क्या हमें इसका उपयोग करना चाहिए?
स्टीफन

17

के लिए उथले आप Object.assign इस्तेमाल कर सकते हैं को कॉपी जो एक ES6 सुविधा है

let x = { name: 'Marek', age: 20 };
let y = Object.assign({}, x);
x === y; //false

गहरी क्लोनिंग के लिए इसका उपयोग न करें


3
गहरी क्लोनिंग के लिए क्या इस्तेमाल किया जा सकता है?
डीबी

15

बताए अनुसार बर्टेंडग का उपयोग करें। कोणीय अब इस विधि का कारण नहीं है, क्योंकि कोणीय 1 एक स्टैंड-अलोन ढांचा था, और बाहरी पुस्तकालय अक्सर कोणीय निष्पादन संदर्भ के साथ मुद्दों में भागते थे। कोणीय 2 में वह समस्या नहीं है, इसलिए आप जो भी पुस्तकालय चाहते हैं उसका उपयोग करें।

https://lodash.com/docs#cloneDeep


8

यदि आप एक श्रेणी उदाहरण की प्रतिलिपि बनाना चाहते हैं, तो आप Object.assign का भी उपयोग कर सकते हैं, लेकिन आपको पहले पैरामीटर ({} के बजाय) के रूप में एक नया उदाहरण पास करना होगा:

class MyClass {
    public prop1: number;
    public prop2: number;

    public summonUnicorn(): void {
        alert('Unicorn !');
    }
}

let instance = new MyClass();
instance.prop1 = 12;
instance.prop2 = 42;

let wrongCopy = Object.assign({}, instance);
console.log(wrongCopy.prop1); // 12
console.log(wrongCopy.prop2); // 42
wrongCopy.summonUnicorn() // ERROR : undefined is not a function

let goodCopy = Object.assign(new MyClass(), instance);
console.log(goodCopy.prop1); // 12
console.log(goodCopy.prop2); // 42
goodCopy.summonUnicorn() // It works !

8

सबसे सरल समाधान जो मैंने पाया है:

let yourDeepCopiedObject = _.cloneDeep(yourOriginalObject);

* महत्वपूर्ण चरण: आपको इसे उपयोग करने के लिए लॉश स्थापित करना होगा (जो अन्य उत्तरों से स्पष्ट नहीं था):

$ npm install --save lodash

$ npm install --save @types/lodash

और फिर इसे अपनी ts फ़ाइल में आयात करें:

import * as _ from "lodash";

7

जैसा कि दूसरों ने पहले ही बताया है, लॉश या अंडरस्कोर का उपयोग करना शायद सबसे अच्छा समाधान है। लेकिन अगर आपको किसी और चीज़ के लिए उन पुस्तकालयों की ज़रूरत नहीं है, तो आप शायद कुछ इस तरह का उपयोग कर सकते हैं:

  function deepClone(obj) {

    // return value is input is not an Object or Array.
    if (typeof(obj) !== 'object' || obj === null) {
      return obj;    
    }

    let clone;

    if(Array.isArray(obj)) {
      clone = obj.slice();  // unlink Array reference.
    } else {
      clone = Object.assign({}, obj); // Unlink Object reference.
    }

    let keys = Object.keys(clone);

    for (let i=0; i<keys.length; i++) {
      clone[keys[i]] = deepClone(clone[keys[i]]); // recursively unlink reference to nested objects.
    }

    return clone; // return unlinked clone.

  }

यही हमने करने का फैसला किया।


1
// उन तारीखों को अनलिंक करने के लिए जिन्हें हम जोड़ सकते हैं: if (pro.prototype.toString.call (obj) === '[ऑब्जेक्ट डेट]') {नई तारीख लौटाएं (obj.getTime ()); }
A_J

1
या उदाहरण के प्रकार का उपयोग कर तारीख की जाँच करें - यदि (obj उदाहरण तिथि) {नई तिथि लौटाएँ (obj.getTime ())}
अनूप इसहाक

0

मुझे इस फ़ीचर की ज़रूरत थी बस मेरे ऐप के 'मॉडल' (कच्ची बैकेंड डेटा ऑब्जेक्ट्स में कनवर्ट)। इसलिए मैंने Object.create (निर्दिष्ट प्रोटोटाइप से नई वस्तु बनाएं) और Object.assign (ऑब्जेक्ट्स के बीच कॉपी गुण ) का उपयोग करके समाप्त किया । मैन्युअल रूप से गहरी प्रतिलिपि को संभालने की आवश्यकता है। मैंने इसके लिए एक जिस्ट बनाया ।


0

एक ही मुद्दा था, और गहरी क्लोनिंग के लिए किसी भी प्लगइन्स का उपयोग नहीं करना चाहता था:

static deepClone(object): any {
        const cloneObj = (<any>object.constructor());
        const attributes = Object.keys(object);
        for (const attribute of attributes) {
            const property = object[attribute];

            if (typeof property === 'object') {
                cloneObj[attribute] = this.deepClone(property);
            } else {
                cloneObj[attribute] = property;
            }
        }
        return cloneObj;
    }

क्रेडिट: मैंने इस फ़ंक्शन को अधिक पठनीय बनाया है , कृपया नीचे इसकी कार्यक्षमता के अपवादों की जांच करें


0

मैंने Angular 5 या उच्चतर के साथ उपयोग करने के लिए एक सेवा बनाई है, यह angular.copy ()angularjs के आधार का उपयोग करता है , यह मेरे लिए अच्छा काम करता है। इसके अतिरिक्त अन्य कार्य भी हैं isUndefined, आदि मुझे आशा है कि यह मदद करता है। किसी भी अनुकूलन की तरह, यह जानना अच्छा होगा। सादर

import { Injectable } from '@angular/core';

@Injectable({providedIn: 'root'})
export class AngularService {

  private TYPED_ARRAY_REGEXP = /^\[object (?:Uint8|Uint8Clamped|Uint16|Uint32|Int8|Int16|Int32|Float32|Float64)Array\]$/;
  private stackSource = [];
  private stackDest = [];

  constructor() { }

  public isNumber(value: any): boolean {
    if ( typeof value === 'number' ) { return true; }
    else { return false; }
  }

  public isTypedArray(value: any) {
    return value && this.isNumber(value.length) && this.TYPED_ARRAY_REGEXP.test(toString.call(value));
  }

  public isArrayBuffer(obj: any) {
    return toString.call(obj) === '[object ArrayBuffer]';
  }

  public isUndefined(value: any) {return typeof value === 'undefined'; }

  public isObject(value: any) {  return value !== null && typeof value === 'object'; }

  public isBlankObject(value: any) {
    return value !== null && typeof value === 'object' && !Object.getPrototypeOf(value);
  }

  public isFunction(value: any) { return typeof value === 'function'; }

  public setHashKey(obj: any, h: any) {
    if (h) { obj.$$hashKey = h; }
    else { delete obj.$$hashKey; }
  }

  private isWindow(obj: any) { return obj && obj.window === obj; }

  private isScope(obj: any) { return obj && obj.$evalAsync && obj.$watch; }


  private copyRecurse(source: any, destination: any) {

    const h = destination.$$hashKey;

    if (Array.isArray(source)) {
      for (let i = 0, ii = source.length; i < ii; i++) {
        destination.push(this.copyElement(source[i]));
      }
    } else if (this.isBlankObject(source)) {
      for (const key of Object.keys(source)) {
        destination[key] = this.copyElement(source[key]);
      }
    } else if (source && typeof source.hasOwnProperty === 'function') {
      for (const key of Object.keys(source)) {
        destination[key] = this.copyElement(source[key]);
      }
    } else {
      for (const key of Object.keys(source)) {
        destination[key] = this.copyElement(source[key]);
      }
    }
    this.setHashKey(destination, h);
    return destination;
  }

  private copyElement(source: any) {

    if (!this.isObject(source)) {
      return source;
    }

    const index = this.stackSource.indexOf(source);

    if (index !== -1) {
      return this.stackDest[index];
    }

    if (this.isWindow(source) || this.isScope(source)) {
      throw console.log('Cant copy! Making copies of Window or Scope instances is not supported.');
    }

    let needsRecurse = false;
    let destination = this.copyType(source);

    if (destination === undefined) {
      destination = Array.isArray(source) ? [] : Object.create(Object.getPrototypeOf(source));
      needsRecurse = true;
    }

    this.stackSource.push(source);
    this.stackDest.push(destination);

    return needsRecurse
      ? this.copyRecurse(source, destination)
      : destination;
  }

  private copyType = (source: any) => {

    switch (toString.call(source)) {
      case '[object Int8Array]':
      case '[object Int16Array]':
      case '[object Int32Array]':
      case '[object Float32Array]':
      case '[object Float64Array]':
      case '[object Uint8Array]':
      case '[object Uint8ClampedArray]':
      case '[object Uint16Array]':
      case '[object Uint32Array]':
        return new source.constructor(this.copyElement(source.buffer), source.byteOffset, source.length);

      case '[object ArrayBuffer]':
        if (!source.slice) {
          const copied = new ArrayBuffer(source.byteLength);
          new Uint8Array(copied).set(new Uint8Array(source));
          return copied;
        }
        return source.slice(0);

      case '[object Boolean]':
      case '[object Number]':
      case '[object String]':
      case '[object Date]':
        return new source.constructor(source.valueOf());

      case '[object RegExp]':
        const re = new RegExp(source.source, source.toString().match(/[^\/]*$/)[0]);
        re.lastIndex = source.lastIndex;
        return re;

      case '[object Blob]':
        return new source.constructor([source], {type: source.type});
    }

    if (this.isFunction(source.cloneNode)) {
      return source.cloneNode(true);
    }
  }

  public copy(source: any, destination?: any) {

    if (destination) {
      if (this.isTypedArray(destination) || this.isArrayBuffer(destination)) {
        throw console.log('Cant copy! TypedArray destination cannot be mutated.');
      }
      if (source === destination) {
        throw console.log('Cant copy! Source and destination are identical.');
      }

      if (Array.isArray(destination)) {
        destination.length = 0;
      } else {
        destination.forEach((value: any, key: any) => {
          if (key !== '$$hashKey') {
            delete destination[key];
          }
        });
      }

      this.stackSource.push(source);
      this.stackDest.push(destination);
      return this.copyRecurse(source, destination);
    }

    return this.copyElement(source);
  }
}


0

मेरे साथ-साथ आपको काम की समस्या का सामना करना पड़ा। मेरा समाधान यह था:

  copyFactory = (() ->
    resource = ->
      resource.__super__.constructor.apply this, arguments
      return
    this.extendTo resource
    resource
  ).call(factory)

0
let newObj = JSON.parse(JSON.stringify(obj))

JSON.stringify()विधि JavaScript ऑब्जेक्ट या JSON स्ट्रिंग के लिए मूल्य धर्मान्तरित


2
यह पहले से ही ऊपर कहा गया है कि यह इसका इलाज करने का सबसे खराब तरीका है!
एलेसेंड्रो

0

आप जैसे ऐरे को क्लोन कर सकते हैं

 this.assignCustomerList = Object.assign([], this.customerList);

और ऑब्जेक्ट को क्लोन की तरह

this.assignCustomer = Object.assign({}, this.customer);

0

यदि आप पहले से ही लॉश का उपयोग नहीं कर रहे हैं, तो मैं इसे केवल इस एक विधि के लिए स्थापित करने की अनुशंसा नहीं करूंगा। मैं इसके बजाय 'क्लोन' जैसे अधिक विशिष्ट विशेष पुस्तकालय का सुझाव देता हूं:

npm install clone
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.