टाइपस्क्रिप्ट - क्लोनिंग ऑब्जेक्ट


187

मेरे पास एक सुपर क्लास है जो Entityकई उपवर्गों के लिए माता-पिता ( ) है Customer, ( Product, ProductCategory...)

मैं गतिशील रूप से एक ऑब्जेक्ट को क्लोन करने के लिए देख रहा हूं जिसमें टाइपस्क्रिप्ट में विभिन्न उप ऑब्जेक्ट शामिल हैं।

उदाहरण में: एक 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;
}

newनिम्न त्रुटि जब यह जावास्क्रिप्ट को transpiled है उगता है:error TS2351: Cannot use 'new' with an expression whose type lacks a call or construct signature.

हालांकि स्क्रिप्ट काम करती है, मैं ट्रांसप्‍लेड एरर से छुटकारा पाना चाहूंगा

जवाबों:


255

विशिष्ट मुद्दे को हल करना

आप संकलक को यह बताने के लिए एक प्रकार के दावे का उपयोग कर सकते हैं कि आप बेहतर जानते हैं:

public clone(): any {
    var cloneObj = new (this.constructor() as any);
    for (var attribut in this) {
        if (typeof this[attribut] === "object") {
            cloneObj[attribut] = this[attribut].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

customer.name = 'Misha';
customer.example = new Example("MishaType");

// clone sees changes to original 
alert(clone.name + ' ' + clone.example.type); // Misha MishaType

clone.name = 'Steve';
clone.example.type = 'SteveType';

// original sees changes to clone
alert(customer.name + ' ' + customer.example.type); // Misha 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 = deepCopy(customer) as 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.3 टाइपस्क्रिप्ट के साथ शिकायत करना बंद कर देता है, लेकिन एक बार जावास्क्रिप्ट में यह त्रुटि फेंक देगा। टाइपस्क्रिप्ट 1.4.1, इसे जाने नहीं देंगे।
डेविड लेबर

1
क्या आप स्पष्ट करना चाहेंगे कि आप इसका उपयोग कैसे करते हैं? मैंने अपनी वस्तु की एक विधि के रूप में शामिल किया और फिर एक त्रुटि मिली कह रही है कि एक फ़ंक्शन नहीं है ...
megalucio

1
मुझे निम्न त्रुटि मिल रही है: "ERROR TypeError: this.constructor (...) कोई निर्माता नहीं है"
michali

3
क्या आपने अभी उस ग्राहक का एक सार्वजनिक उदाहरण बनाया है?
ब्लेयर कोनोली

1
क्या कोई टीएल; डीआर मेरे लिए जो सभी उत्तरों में दिए गए समाधानों में से किस प्रकार के ओओ प्रकार को संरक्षित कर सकता है, अर्थात cloned instanceof MyClass === true?
स्ज़ेप्पन होलिज़्यूस्की

177

1. उपयोग प्रसार ऑपरेटर

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

प्रसार ऑपरेटर 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 के प्लस हैं कि प्रोटोटाइप में घोषित कोई भी कार्य हमारे नए बनाए गए ऑब्जेक्ट में उपलब्ध होगा।


उथली नकल के बारे में कुछ बातें

उथला प्रतिलिपि पुराने के सभी क्षेत्रों में नई वस्तु में डालती है, लेकिन इसका मतलब यह भी है कि यदि मूल वस्तु में समग्र प्रकार के क्षेत्र (ऑब्जेक्ट, सरणियां आदि) हैं, तो उन क्षेत्रों को उसी संदर्भ में नए ऑब्जेक्ट में डाल दिया जाता है। मूल वस्तु में ऐसा क्षेत्र नई वस्तु में परिलक्षित होगा।

यह शायद एक नुकसान की तरह दिखता है, लेकिन वास्तव में ऐसी स्थिति जब पूरे जटिल ऑब्जेक्ट को कॉपी करने की आवश्यकता होती है, दुर्लभ है। Shallow copy अधिकांश मेमोरी का पुनः उपयोग करेगा जिसका अर्थ है कि गहरी कॉपी की तुलना में बहुत सस्ता है।


गहरी नकल

डीप कॉपी के लिए स्प्रेड ऑपरेटर काम कर सकता है।

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

उपरोक्त कोड ने obj1 की गहरी प्रतिलिपि बनाई। समग्र क्षेत्र "कॉम्प्लेक्स" को भी obj2 में कॉपी किया गया था। म्यूटेशन फ़ील्ड "कॉम्प्लेक्स" प्रतिलिपि को प्रतिबिंबित नहीं करेगा।


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

3
आप इसके बजाय ES2015 और टाइपस्क्रिप्ट डेवलपर्स भी देखेंगे, जो 1 पैरामीटर से एक वस्तु बनाता है (मेरे मामले में एक खाली एक) और दूसरे और बाद के let b = Object.assign({}, a);
पारमेस

@KenRimple आप 100% सही हैं, मैंने कुछ और जानकारी जोड़ी है।
मैकीज सिकोरा


5
Object.assign गहरी वस्तुओं के लिए समस्याएं पैदा करेगा। उदाहरण के लिए {name: 'x', मान: ['a', 'b', 'c']}। क्लोन करने के लिए Object.assign का उपयोग करने के बाद, दोनों ऑब्जेक्ट वैल्यू ऐरे को साझा करते हैं, इसलिए एक को अपडेट करना दूसरे को प्रभावित करता है। देखें: developer.mozilla.org/en/docs/Web/JavaScript/Reference/… ('डीप क्लोन के लिए चेतावनी' अनुभाग)। यह कहता है: गहरी क्लोनिंग के लिए, हमें अन्य विकल्पों का उपयोग करने की आवश्यकता है। ऐसा तब होता है क्योंकि Object.assign () प्रॉपर्टी संदर्भ को कॉपी करता है जब संपत्ति को सौंपा जा रहा है।
मीर

48

इसे इस्तेमाल करे:

let copy = (JSON.parse(JSON.stringify(objectToCopy)));

यह एक अच्छा समाधान है जब तक कि आप बहुत बड़ी वस्तुओं का उपयोग नहीं कर रहे हैं या आपकी वस्तु में अचूक गुण हैं।

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

getCopy(): YourClassName{
    return (JSON.parse(JSON.stringify(this)));
}

या स्थिर तरीके से:

static createCopy(objectToCopy: YourClassName): YourClassName{
    return (JSON.parse(JSON.stringify(objectToCopy)));
}

5
यह ठीक है, लेकिन आपको ध्यान रखना चाहिए कि आप प्रोटोटाइप की जानकारी खो देंगे और सीरियल / पार्स होने पर सभी प्रकार के json में समर्थित नहीं हैं।
स्टेनिस्लाव ई। गोवरोव

1
इसके अलावा यह ऊपर दी गई deepCopy फ़ंक्शन की तुलना में कम कुशल लगता है
मोजतबा

मेरे पास यह त्रुटि है: "जब मैं उपयोग करता हूं तो JSON को परिपत्र संरचना को बदलना" (JSON.parse (JSON.stringify (objectToCopy))); "
सेड्रिक अर्नोल्ड

केवल 98% मामलों में काम करता है। undefinedकम से कम मूल्य के साथ लापता चाबियाँ हो सकती हैं । यदि objectToCopy = { x : undefined};तब चलाने के बाद आपका कोड Object.keys(objectToCopy).lengthहै 1, जबकि Object.keys(copy).lengthहै 0
एडिन

33

टाइपस्क्रिप्ट / जावास्क्रिप्ट के पास उथले क्लोनिंग के लिए अपना ऑपरेटर है:

let shallowClone = { ...original };

15

टाइपस्क्रिप्ट 2.1 में शुरू की गई "ऑब्जेक्ट स्प्रेड" के साथ उथली प्रतिलिपि प्राप्त करना आसान है

यह टाइपस्क्रिप्ट: let copy = { ...original };

इस जावास्क्रिप्ट का उत्पादन करता है:

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


2
नोट: यह एक उथली प्रति बनाएगा
जिमी केन

11

टाइप करने योग्य गहरी क्लोन के लिए, टाइप जानकारी के साथ,

export function clone<T>(a: T): T {
  return JSON.parse(JSON.stringify(a));
}

1
यह सहारा के क्रम को बदल सकता है। कुछ लोगों के लिए बस एक चेतावनी। इसके अलावा यह तारीखों को ठीक से नहीं संभालता है।
पंगम्मा

यह प्रॉप्स के क्रम को बदल सकता है - npmjs.com/package/es6-json-stable-stringify के बजायJSON.stringify
Polv

@Polv, अगर कोई ऑब्जेक्ट में कुंजियों के क्रम पर भरोसा कर रहा है, तो मुझे लगता है कि उन्हें इससे भी बड़ी समस्या है clone। :)
एडिन

यह समाधान undefinedमूल्य के साथ कुंजियों को याद कर सकता है । उपरोक्त समान उत्तर पर मेरी टिप्पणी देखें: stackoverflow.com/questions/28150967/typescript-cloning-object/…
Aidin

7

इस पर मेरी ले:

Object.assign(...) केवल गुणों को कॉपी करता है और हम प्रोटोटाइप और तरीके खो देते हैं।

Object.create(...) मेरे लिए गुणों की नकल नहीं कर रहा है और सिर्फ एक प्रोटोटाइप बना रहा है।

मेरे लिए जो काम किया गया है वह एक प्रोटोटाइप बना रहा है Object.create(...)और इसका उपयोग करके गुणों को कॉपी करना है Object.assign(...):

तो एक वस्तु के लिए foo, इस तरह क्लोन बनाएं:

Object.assign(Object.create(foo), foo)

यहाँ बहुत सूक्ष्म बात चल रही है। आप वास्तव fooमें clonedFoo(नई वस्तु) के प्रोटोटाइप माता-पिता बन रहे हैं । हालांकि यह ठीक लग सकता है, आपको यह ध्यान रखना चाहिए कि एक लापता संपत्ति को प्रोटोटाइप श्रृंखला में देखा जाएगा, इसलिए const a = { x: 8 }; const c = Object.assign(Object.create(a), a); delete c.x; console.log(c.x);8 प्रिंट करता है, जबकि होना चाहिए undefined! (आरईपीएल लिंक: repl.it/repls/CompetitivePreemptiveKeygen )
Aidin

इसके अतिरिक्त, यदि आप बाद में एक संपत्ति जोड़ते हैं foo, तो यह स्वचालित रूप से दिखाई देगा clonedFoo! जैसे foo.y = 9; console.log(clonedFoo.y)बाहर प्रिंट होगा 9के बजाय undefined। यह बहुत संभावना है कि यह वह नहीं है जो आप पूछ रहे हैं!
Aidin

@ ऐडिन तो एक गहरी प्रतिलिपि कैसे सुनिश्चित करें?
मुहम्मद अली

इस सवाल है, जो (जैसे रिकर्सिवली प्रति-दर-मूल्य क्या कर रहा है में किसी भी अन्य समाधान stackoverflow.com/a/53025968 marckassay द्वारा) सुनिश्चित करना है कि, के बाद से वहाँ है स्रोत ऑब्जेक्ट के लिए कोई संदर्भ लक्ष्य वस्तु में बनाए रखा जा रहा है।
एडिन

5

आप कुछ इस तरह से भी हो सकते हैं:

class Entity {
    id: number;

    constructor(id: number) {
        this.id = id;
    }

    clone(): this {
        return new (this.constructor as typeof Entity)(this.id) as this;
    }
}

class Customer extends Entity {
    name: string;

    constructor(id: number, name: string) {
        super(id);
        this.name = name;
    }

    clone(): this {
        return new (this.constructor as typeof Customer)(this.id, this.name) as this;
    }
}

बस सुनिश्चित करें कि आप cloneसभी Entityउपवर्गों में विधि को ओवरराइड करते हैं अन्यथा आप आंशिक क्लोन के साथ समाप्त हो जाएंगे।

वापसी प्रकार thisहमेशा उदाहरण के प्रकार से मेल खाता है।


4

"lodash.clonedeep": "^4.5.0"अपने में जोड़ें package.json। तो इस तरह का उपयोग करें:

import * as _ from 'lodash';

...

const copy = _.cloneDeep(original)

3

यहाँ मेरा मैश-अप है! और यहाँ एक StackBlitz लिंक है। इसका वर्तमान केवल सरल प्रकार और ऑब्जेक्ट प्रकारों की प्रतिलिपि बनाने तक सीमित है, लेकिन आसानी से संशोधित किया जा सकता है मुझे लगता है।

   let deepClone = <T>(source: T): { [k: string]: any } => {
      let results: { [k: string]: any } = {};
      for (let P in source) {
        if (typeof source[P] === 'object') {
          results[P] = deepClone(source[P]);
        } else {
          results[P] = source[P];
        }
      }
      return results;
    };

1
जहाँ तक मैं देख सकता हूँ बहुत अच्छी तरह से काम करता है। हालाँकि, typeof nullएक ऑब्जेक्ट भी है, इसलिए क्वेरी if (source[P] !== null && typeof source[P] === 'object')इसके बजाय होनी चाहिए । अन्यथा आपके अशक्त मूल्य एक खाली वस्तु में बदल जाएंगे।
मोर्टेनमॉल्डर

3

यदि आपको यह त्रुटि मिलती है:

TypeError: this.constructor(...) is not a function

यह सही स्क्रिप्ट है:

public clone(): any {
    var cloneObj = new (<any>this.constructor)(); // line fixed
    for (var attribut in this) {
        if (typeof this[attribut] === "object") {
            cloneObj[attribut] = this[attribut].clone();
        } else {
            cloneObj[attribut] = this[attribut];
        }
    }
    return cloneObj;
}

4
सही है cloneObj[attribut] = this.clone();? या आपका मतलब हैcloneObj[attribut] = this[attribut].clone();
सर्गिन्हो

2

खुद इस समस्या के सामने आया और अंत में एक छोटी सी लाइब्रेरी क्लोन करने योग्य-टीएस लिखी जो एक अमूर्त वर्ग प्रदान करती है, जो किसी भी वर्ग के लिए एक क्लोन पद्धति का विस्तार करती है। अमूर्त वर्ग फेंटन द्वारा स्वीकृत उत्तर में वर्णित डीप कॉपी फ़ंक्शन को केवल मूल वस्तु के वर्ग को संरक्षित करने के लिए प्रतिस्थापित copy = {};करता copy = Object.create(originalObj)है। यहाँ कक्षा का उपयोग करने का एक उदाहरण है।

import {Cloneable, CloneableArgs} from 'cloneable-ts';

// Interface that will be used as named arguments to initialize and clone an object
interface PersonArgs {
    readonly name: string;
    readonly age: number;
}

// Cloneable abstract class initializes the object with super method and adds the clone method
// CloneableArgs interface ensures that all properties defined in the argument interface are defined in class
class Person extends Cloneable<TestArgs>  implements CloneableArgs<PersonArgs> {
    readonly name: string;
    readonly age: number;

    constructor(args: TestArgs) {
        super(args);
    }
}

const a = new Person({name: 'Alice', age: 28});
const b = a.clone({name: 'Bob'})
a.name // Alice
b.name // Bob
b.age // 28

या आप बस Cloneable.cloneसहायक विधि का उपयोग कर सकते हैं :

import {Cloneable} from 'cloneable-ts';

interface Person {
    readonly name: string;
    readonly age: number;
}

const a: Person = {name: 'Alice', age: 28};
const b = Cloneable.clone(a, {name: 'Bob'})
a.name // Alice
b.name // Bob
b.age // 28    

1

टाइपस्क्रिप्ट 3.7 जारी होने के बाद, पुनरावर्ती प्रकार के उपनाम अब समर्थित हैं और यह हमें एक प्रकार के सुरक्षित deepCopy()कार्य को परिभाषित करने की अनुमति देता है :

// DeepCopy type can be easily extended by other types,
// like Set & Map if the implementation supports them.
type DeepCopy<T> =
    T extends undefined | null | boolean | string | number ? T :
    T extends Function | Set<any> | Map<any, any> ? unknown :
    T extends ReadonlyArray<infer U> ? Array<DeepCopy<U>> :
    { [K in keyof T]: DeepCopy<T[K]> };

function deepCopy<T>(obj: T): DeepCopy<T> {
    // implementation doesn't matter, just use the simplest
    return JSON.parse(JSON.stringify(obj));
}

interface User {
    name: string,
    achievements: readonly string[],
    extras?: {
        city: string;
    }
}

type UncopiableUser = User & {
    delete: () => void
};

declare const user: User;
const userCopy: User = deepCopy(user); // no errors

declare const uncopiableUser: UncopiableUser;
const uncopiableUserCopy: UncopiableUser = deepCopy(uncopiableUser); // compile time error

खेल का मैदान


0

छेद ऑब्जेक्ट की सामग्री के एक साधारण क्लोन के लिए, मैं बस उदाहरण को स्ट्रिंग और पार्स करता हूं:

let cloneObject = JSON.parse(JSON.stringify(objectToClone))

जबकि मैं objectToClone ट्री में डेटा बदलता हूं, क्लोन क्लोन में कोई बदलाव नहीं हुआ है। यह मेरा अनुरोध था।

आशा है कि यह मदद करेगा


1
undefinedमूल्य के साथ चाबियाँ याद कर सकते हैं । ऊपर दिए गए समान उत्तर पर मेरी टिप्पणी देखें: stackoverflow.com/questions/28150967/typescript-cloning-object/…
Aidin

0

मैंने समाप्त कर दिया:

public clone(): any {
  const result = new (<any>this.constructor);

  // some deserialization code I hade in place already...
  // which deep copies all serialized properties of the
  // object graph
  // result.deserialize(this)

  // you could use any of the usggestions in the other answers to
  // copy over all the desired fields / properties

  return result;
}

इसलिये:

var cloneObj = new (<any>this.constructor());

@Fenton से रनटाइम त्रुटियाँ दीं।

टाइपस्क्रिप्ट संस्करण: 2.4.2


0

कैसे अच्छे पुराने jQuery के बारे में ?! यहाँ गहरा क्लोन है:

var clone = $.extend(true, {}, sourceObject);

इस प्रश्न को JQuery टैग नहीं किया गया था और न ही JQuery का उल्लेख किया गया था। यह भी एक बड़े क्लोन करने के लिए एक परियोजना में JQuery को शामिल करने के लिए बड़े पैमाने पर ओवरहेड होगा।
लुईसएम

यह काफी उचित है, लेकिन ओपी क्लोन करने के तरीके के बारे में नहीं है, यह उस कोड में एक मुद्दे की पहचान करने के बारे में है जो आपने प्रदान किया था और आपने क्लोनिंग के jQuery के तरीके के साथ वास्तव में सवाल का जवाब दिए बिना जवाब दिया था। मैं वह नहीं हूं, जिसने आपको नीचा दिखाया है, लेकिन मेरा मानना ​​है कि हो सकता है कि आपको क्यों उकसाया गया हो।
लेविस

0

मैंने एक जेनेरिक कॉपी / क्लोन सेवा बनाने के लिए एक स्टैब लिया जो नेस्टेड ऑब्जेक्ट्स के लिए प्रकारों को बनाए रखता है। अगर मैं कुछ गलत कर रहा हूं, तो प्रतिक्रिया पसंद करेंगे, लेकिन ऐसा लगता है कि यह अभी तक काम कर रहा है ...

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

@Injectable()
export class CopyService {

  public deepCopy<T>(objectToClone: T): T {
    // If it's a simple type or null, just return it.
    if (typeof objectToClone === 'string' ||
      typeof objectToClone === 'number' ||
      typeof objectToClone === 'undefined' ||
      typeof objectToClone === 'symbol' ||
      typeof objectToClone === 'function' ||
      typeof objectToClone === 'boolean' ||
      objectToClone === null
    ) {
      return objectToClone;
    }

    // Otherwise, check if it has a constructor we can use to properly instantiate it...
    let ctor = Object.getPrototypeOf(objectToClone).constructor;
    if (ctor) {
      let clone = new ctor();

      // Once we've instantiated the correct type, assign the child properties with deep copies of the values
      Object.keys(objectToClone).forEach(key => {
        if (Array.isArray(objectToClone[key]))
          clone[key] = objectToClone[key].map(item => this.deepCopy(item));
        else
          clone[key] = this.deepCopy(objectToClone[key]);
      });

      if (JSON.stringify(objectToClone) !== JSON.stringify(clone))
        console.warn('object cloned, but doesnt match exactly...\nobject: ' + JSON.stringify(objectToClone) + "\nclone: " + JSON.stringify(clone))

      // return our cloned object...
      return clone;
    }
    else {
      //not sure this will ever get hit, but figured I'd have a catch call.
      console.log('deep copy found something it didnt know: ' + JSON.stringify(objectToClone));
      return objectToClone;
    }
  }
}

0

टाइपस्क्रिप्ट में मैं कोणीय के साथ परीक्षण करता हूं, और यह ठीक है

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] = this.deepCopy(obj[i]);
            }
            return copy;
        }

        // Handle Object
        if (obj instanceof Object) {
            copy = {};
            for (var attr in obj) {
                if (obj.hasOwnProperty(attr)) copy[attr] = this.deepCopy(obj[attr]);
            }
            return copy;
        }

        throw new Error("Unable to copy obj! Its type isn't supported.");
    }

0

किसी ऑब्जेक्ट को डीप क्लोनिंग करने के लिए जिसमें अन्य ऑब्जेक्ट्स, एरेज़ और इतने पर मैं उपयोग कर सकता हूं:

const clone = <T>(source: T): T => {
  if (source === null) return source

  if (source instanceof Date) return new Date(source.getTime()) as any

  if (source instanceof Array) return source.map((item: any) => clone<any>(item)) as any

  if (typeof source === 'object' && source !== {}) {
    const clonnedObj = { ...(source as { [key: string]: any }) } as { [key: string]: any }
    Object.keys(clonnedObj).forEach(prop => {
      clonnedObj[prop] = clone<any>(clonnedObj[prop])
    })

    return clonnedObj as T
  }

  return source
}

उपयोग:

const obj = {a: [1,2], b: 's', c: () => { return 'h'; }, d: null, e: {a:['x'] }}
const objClone = clone(obj)

0

आप फैलाने वाले सिंटैक्स के साथ विनाशकारी असाइनमेंट का उपयोग कर सकते हैं :

var obj = {id = 1, name = 'product1'};
var clonedObject = {...obj};

1
हालांकि यह कोड प्रश्न का उत्तर दे सकता है, लेकिन यह समस्या का हल कैसे और / या इसके बारे में अतिरिक्त संदर्भ प्रदान करता है, इससे उत्तर के दीर्घकालिक मूल्य में सुधार होगा।
लियोपल

-2

यदि आपके पास पहले से ही लक्ष्य वस्तु है, तो आप इसे नए सिरे से नहीं बनाना चाहते (जैसे यदि कोई सरणी अद्यतन कर रहे हैं) तो आपको गुणों को कॉपी करना होगा।
अगर इस तरह से किया है:

Object.keys(source).forEach((key) => {
    copy[key] = source[key]
})

प्रशंसा का कारण है। (शीर्षक "संस्करण 2" देखें)


कार्य? सरणी? दिनांक ऑब्जेक्ट्स? प्रकारों का संरक्षण? और निश्चित रूप से वस्तुओं के बारे में क्या? यदि उपरोक्त फ़ंक्शन किसी भी उपरोक्त प्रकार का सामना करता है तो यह गहरे क्लोन में विफल हो जाएगा। आपने उसी डेटा के संदर्भों की प्रतिलिपि बनाई होगी। जब वे क्लोन किए गए ऑब्जेक्ट के बाल गुणों को संपादित करने के लिए जाते हैं, तो वे मूल वस्तु को भी संपादित करेंगे।
पंगम्मा
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.