প্রকারলিপি - ক্লোনিং অবজেক্ট


184

আমি একটি সুপার ক্লাস হয় যে আছে পিতা বা মাতা ( 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.

যদিও স্ক্রিপ্টটি কাজ করে তবে আমি স্থানান্তরিত ত্রুটি থেকে মুক্তি পেতে চাই

উত্তর:


252

নির্দিষ্ট সমস্যা সমাধান করা

আপনি আরও ভাল জানেন এমন সংকলকটি বলতে আপনি একটি প্রকারের দৃser়তা ব্যবহার করতে পারেন:

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: অবজেক্ট.সেসাইন

বৈশিষ্ট্য: হ্যাঁ
পদ্ধতি: কোন
গভীর অনুলিপি: না

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: অবজেক্ট.ক্রিট

বৈশিষ্ট্য: উত্তরাধিকারী
পদ্ধতি: উত্তরাধিকার সূত্রে
গভীর অনুলিপি: অগভীর উত্তরাধিকারী (গভীর পরিবর্তনগুলি মূল এবং ক্লোন উভয়কেই প্রভাবিত করে)

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, এটি যেতে দেয় না।
ডেভিড Laberge

আপনি ক্লোনিং করছেন একই ধরণের ফলাফল ফিরে পেতে আপনি জেনেরিক ব্যবহার করতে পারেন।
রবএমসিএম

1
আপনি কীভাবে এটি সঠিকভাবে ব্যবহার করেন তা স্পষ্ট করে বলতে চাইবেন? আমি আমার অবজেক্টের একটি পদ্ধতি হিসাবে অন্তর্ভুক্ত করেছি এবং তারপরে একটি ত্রুটি পেয়েছি যা কোনও ফাংশন নয় ...
megalucio

1
আমি নিম্নলিখিত ত্রুটিটি পাচ্ছি: "এআরআরআর টাইপ ইরার: এটি.কন্সট্রাক্টর (...) কোনও নির্মাণকারী নয়"
মিচালি

3
আপনি কি কেবলমাত্র সেই গ্রাহকের বাইরে সর্বজনীন উদাহরণ তৈরি করেছেন?
ব্লেয়ার কনলি

175

1. স্প্রেড অপারেটর ব্যবহার করুন

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

স্প্রেড অপারেটর সমস্ত ক্ষেত্রকে প্রবৃত্তি 1 থেকে নেওয়া এবং সেগুলি অ্যাজ 2-তে ছড়িয়ে দেয়। ফলস্বরূপ আপনি নতুন রেফারেন্স এবং একই হিসাবে একই ক্ষেত্রের সাথে নতুন বস্তু পাবেন।

মনে রাখবেন এটি অগভীর অনুলিপি, এর অর্থ হ'ল যদি বস্তু বাসা বেঁধে থাকে তবে তার নেস্টেড যৌগিক প্যারামগুলি একই রেফারেন্সের মাধ্যমে নতুন বস্তুতে উপস্থিত থাকবে।

2.Object.assign ()

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

অবজেক্ট.সাইনাইন প্রকৃত অনুলিপি তৈরি করুন তবে কেবল নিজস্ব সম্পত্তি রয়েছে, তাই প্রোটোটাইপের বৈশিষ্ট্য অনুলিপি করা অবজেক্টে উপস্থিত থাকবে না। এটি অগভীর অনুলিপিও।


3.Object.create ()

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

Object.create প্রকৃত ক্লোনিং করছে না , এটি প্রোটোটাইপ থেকে অবজেক্ট তৈরি করছে। সুতরাং যদি এটিতে প্রাথমিক ধরণের বৈশিষ্ট্যগুলি ক্লোন করা উচিত তবে এটি ব্যবহার করুন, কারণ প্রাথমিক ধরণের বৈশিষ্ট্য নির্ধারণ রেফারেন্স দ্বারা করা হয় না।

অবজেক্ট.ক্রিটের ফলস হ'ল প্রোটোটাইপে ঘোষিত যে কোনও ফাংশন আমাদের সদ্য নির্মিত বস্তুতে উপলভ্য হবে।


অগভীর অনুলিপি সম্পর্কে কয়েকটি জিনিস

অগভীর অনুলিপি পুরানোটির সমস্ত ক্ষেত্রকে নতুন বস্তুতে রাখে, তবে এর অর্থ এটিও হ'ল যদি মূল অবজেক্টের সমন্বিত প্রকার ক্ষেত্র (অবজেক্ট, অ্যারে ইত্যাদি) থাকে তবে সেই ক্ষেত্রগুলিকে একই রেফারেন্স সহ নতুন বস্তুতে রাখা হয়। মূল অবজেক্টে এ জাতীয় ক্ষেত্রটির রূপান্তর নতুন অবজেক্টে প্রতিফলিত হবে।

এটি সম্ভবত কোনও অসুবিধাগুলির মতো দেখাচ্ছে তবে পুরো জটিল বস্তুটি অনুলিপি করা দরকার এমন পরিস্থিতি বিরল। অগভীর অনুলিপি বেশিরভাগ স্মৃতি পুনরায় ব্যবহার করবে যার অর্থ গভীর অনুলিপিটির তুলনায় খুব সস্তা।


গভীর কপি

গভীর কপির জন্য স্প্রেড অপারেটর সুবিধাজনক হতে পারে।

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

উপরে কোড অজেক্ট 1 এর গভীর অনুলিপি তৈরি করেছে। যৌগিক ক্ষেত্র "কমপ্লেক্স" এজেজ 2 তেও অনুলিপি করা হয়েছিল। মিউটেশন ক্ষেত্র "জটিল" অনুলিপিটি প্রতিফলিত করবে না।


8
আমি পুরোপুরি সঠিক বলে মনে করি না। Object.create(obj1)একটি নতুন অবজেক্ট তৈরি করে ওজেট 1 প্রোটোটাইপ হিসাবে নিযুক্ত করে। আপত্তি 1 তে কোনও ক্ষেত্রই অনুলিপি বা ক্লোন নয়। সুতরাং অজ 2 তে সংশোধন না করে ওজেক্ট 1 এ পরিবর্তনগুলি দেখা যাবে, কারণ এর মূলত কোনও বৈশিষ্ট্য নেই। আপনি যদি প্রথমে অজ 2 টি সংশোধন করেন তবে নামটির সাথে অজ 2 এর ক্ষেত্রটি স্তরক্রমের কাছাকাছি হওয়ায় আপনি যে ক্ষেত্রটি নির্ধারণ করেছেন তার জন্য প্রোটোটাইপটি দেখা যাবে না।
কেন রিম্পল

3
আপনি এর পরিবর্তে ES2015 এবং টাইপস্ক্রিপ্ট বিকাশকারীদের এটিও দেখতে পাবেন, যা 1 ম প্যারামিটার থেকে একটি অবজেক্ট তৈরি করে (আমার ক্ষেত্রে এটি একটি খালি) এবং দ্বিতীয় এবং পরবর্তী let b = Object.assign({}, a);
প্যারাম

@ কেনারিম্পল আপনি 100% ঠিক আছেন, আমি আরও কিছু তথ্য যুক্ত করেছি।
ম্যাকিয়েজ সিকোড়া


5
অবজেক্ট.সেসাইন গভীর বস্তুর জন্য সমস্যা তৈরি করবে। উদাহরণস্বরূপ {নাম: 'x', মানগুলি: ['a', 'b', 'c']}} ক্লোন করতে অবজেক্ট.সেসাইন ব্যবহার করার পরে, উভয় বস্তু মান অ্যারে ভাগ করে তাই একটি আপডেট করা অন্যটিকে প্রভাবিত করে। দেখুন: বিকাশকারী.মোজিলা.আর.ইন / ডকস / ওয়েব / জাভা স্ক্রিপ্ট / রেফারেন্স / (('ডিপ ক্লোনারের জন্য সতর্কতা' বিভাগ)। এটি বলে: গভীর ক্লোনিংয়ের জন্য আমাদের অন্যান্য বিকল্প ব্যবহার করা দরকার। এটি কারণ সম্পত্তি বরাদ্দ করা যখন কোনও বস্তু হিসাবে অবজেক্ট.সেসাইন () সম্পত্তি রেফারেন্স অনুলিপি করে।
মেয়ার

45

এটা চেষ্টা কর:

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
এটি ঠিক আছে, তবে আপনার মনে রাখা উচিত যে আপনি সিরিয়ালাইজ / পার্স করার সময় প্রোটোটাইপ তথ্য এবং সমস্ত প্রকারের জেসন সমর্থন করবেন না lose
স্টানিস্লাভ ই। গোভরভ

1
এছাড়াও উপরের সরবরাহ করা ডিপকপি ফাংশনের সাথে তুলনা করা কম দক্ষ বলে মনে হচ্ছে ।
মোজতাবা

আমার এই ত্রুটি রয়েছে: "আমি যখন ব্যবহার করি তখন বিজ্ঞপ্তি কাঠামোটিকে JSON এ রূপান্তর করা" (JSON.parse (JSON.stringify (অবজেক্টটোকপি))); "
সিড্রিক আর্নল্ড

শুধুমাত্র 98% ক্ষেত্রে কাজ করে। undefinedকমপক্ষে, মান সহ কীগুলি অনুপস্থিত হতে পারে । যদি objectToCopy = { x : undefined};আপনার কোড চালানোর পরে Object.keys(objectToCopy).lengthহয় 1, যখন Object.keys(copy).lengthহয় 0
এইডিন

31

অগভীর ক্লোনিংয়ের জন্য টাইপস্ক্রিপ্ট / জাভাস্ক্রিপ্টের নিজস্ব অপারেটর রয়েছে:

let shallowClone = { ...original };

15

টাইপস্ক্রিপ্ট ২.১ এ প্রবর্তিত "অবজেক্ট স্প্রেড" দিয়ে অগভীর অনুলিপি পাওয়া সহজ

এই টাইপস্ক্রিপ্ট: 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));
}

এটি প্রপসের ক্রম পরিবর্তন করতে পারে। কিছু লোকের জন্য কেবল একটি সতর্কতা। এছাড়াও এটি তারিখগুলি সঠিকভাবে পরিচালনা করে না।
পাঙ্গামা

এই সাজসরঞ্জাম ক্রম পরিবর্তন করতে পারেন - চেষ্টা করতে পারে npmjs.com/package/es6-json-stable-stringify পরিবর্তেJSON.stringify
Polv

@ পোলভ, যদি কেউ কোনও বস্তুর কীগুলির ক্রমের উপর নির্ভর করে তবে আমি মনে করি তাদের চেয়ে বড় সমস্যা রয়েছে clone। :)
এইডিন

এই সমাধানটি undefinedমান সহ কীগুলি মিস করতে পারে। উপরের অনুরূপ উত্তরের বিষয়ে আমার মন্তব্য দেখুন: স্ট্যাকওভারফ্লো
টাইপসক্রিপশন -কোলোনিং

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 লিঙ্ক: repl.it/repls/CompetitivePreemptiveKeygen )
Aidin

অতিরিক্তভাবে, আপনি যদি পরে কোনও সম্পত্তি যুক্ত করেন তবে fooএটি স্বয়ংক্রিয়ভাবে প্রদর্শিত হবে clonedFoo! যেমন পরিবর্তে foo.y = 9; console.log(clonedFoo.y)প্রিন্ট আউট 9হবে undefined। এটি সম্ভবত আপনি যা চাইছেন তা নয়!
এইডিন

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সর্বদা উদাহরণের ধরণের সাথে মেলে।


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

এই সমস্যাটি আমি নিজেই পেরিয়ে এসেছি এবং শেষে একটি ছোট গ্রন্থাগার ক্লোনিয়েবল-টিএস লিখেছিলাম যা একটি বিমূর্ত শ্রেণি সরবরাহ করে, যা কোনও ক্লাসকে প্রসারিত করে এমন ক্লোন পদ্ধতি প্রয়োগ করে। বিমূর্ত বর্গ দ্বারা মধ্যে Fenton শুধুমাত্র প্রতিস্থাপন গৃহীত উত্তর বর্ণিত ডীপ কপি ফাংশন ধার 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    

2

এই যে আমার ম্যাশ আপ! এবং এটির সাথে এখানে একটি স্ট্যাকব্লিটজ লিঙ্ক । এটি বর্তমানে কেবলমাত্র সহজ ধরণের এবং অবজেক্টের ধরণের অনুলিপি করতে সীমাবদ্ধ তবে এটি আমি সহজেই পরিবর্তন করতে পারি I

   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')পরিবর্তে হওয়া উচিত । অন্যথায় আপনার নাল মানগুলি একটি খালি বস্তুতে পরিণত হবে।
মর্টেনমোল্ডার

2

"lodash.clonedeep": "^4.5.0"আপনার যোগ করুন package.json। তারপরে এটি ব্যবহার করুন:

import * as _ from 'lodash';

...

const copy = _.cloneDeep(original)

1

যেহেতু টাইপস্ক্রিপ্ট ৩.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))

আমি যেখানে অবজেক্টটোক্লোন ট্রিতে ডেটা পরিবর্তন করেছি, ক্লোনঅবজেক্টে কোনও পরিবর্তন নেই। এটাই ছিল আমার প্রতিদান।

আশা করি এটি সাহায্য করবে


1
undefinedমান সহ কী মিস করতে পারে । উপরের অনুরূপ উত্তরের বিষয়ে আমার মন্তব্য দেখুন: স্ট্যাকওভারফ্লো
টাইপসক্রিপশন -কোলোনিং

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());

@ ফেন্টন থেকে রানটাইম ত্রুটি দিয়েছে।

টাইপ করা বিষয় সংস্করণ: 2.4.2


0

কিভাবে পুরানো jQuery সম্পর্কে ?! এখানে গভীর ক্লোন রয়েছে:

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

এই প্রশ্নটি জ্যাকুয়েরিকে ট্যাগ করা হয়নি এবং প্রশ্নটিতে জিকুয়েরি উল্লেখ করা হয়নি। একটি গভীর ক্লোন করার জন্য কোনও প্রকল্পে জিকুয়েরি অন্তর্ভুক্ত করাও বিশাল ওভারহেড হবে।
লুইসএম

এটি যথেষ্ট ন্যায্য, তবে ওপি কীভাবে ক্লোন করতে পারে তা নয়, এটি তার দেওয়া কোডটিতে একটি সমস্যা চিহ্নিত করার বিষয়ে এবং আপনি প্রশ্নের উত্তর না দিয়ে ক্লোনিংয়ের 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" দেখুন)


কার্যাবলী? অ্যারেগুলির? তারিখ অবজেক্টস? প্রকার সংরক্ষণ? এবং অবশ্যই কি জিনিস সম্পর্কে? উপরের ফাংশনটি যদি উপরের যে কোনও ধরণের মুখোমুখি হয় তবে এটি গভীর ক্লোন করতে ব্যর্থ হবে। আপনি একই তথ্য রেফারেন্স অনুলিপি করা হবে। তারা যখন ক্লোন করা বস্তুর সন্তানের বৈশিষ্ট্যগুলি সম্পাদনা করতে যায় তারা মূল বস্তুকেও সম্পাদনা করতে পারে।
পাঙ্গামা
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.