কৌণিক কৌণিক কপির বিকল্প কি


135

আমি কীভাবে কোনও বস্তুর অনুলিপি করতে পারি এবং এর কৌনিকটিতে তার উল্লেখটি হারাতে পারি?

অ্যাঙ্গুলারজেএস দিয়ে, আমি ব্যবহার করতে পারি angular.copy(object), তবে এটি কৌণিক ব্যবহার করে কিছুটা ত্রুটি পাচ্ছি।

ছাড়: রেফারেন্সএরর: angularসংজ্ঞায়িত হয়নি


এই সমাধানটি এটির সাহায্য করতে পারে তা পরীক্ষা করুন: লিঙ্ক
নুরডাইন Alouane

অনেক পরিস্থিতিতে আপনি ব্যবহার করতে চাইতে পারেন .copy()তবে বাস্তবে এটির প্রয়োজন হবে না। বিভিন্ন AngJS1 প্রকল্পে আমি দেখেছি, এটি একটি ওভারকিল ছিল, যেখানে সম্পর্কিত কাঠামোর একটি ম্যানুয়াল অনুলিপি একটি ক্লিনার কোডের জন্য তৈরি করত। অ্যাংুলার দল এটি প্রয়োগ না করার সিদ্ধান্তের অংশ হতে পারে।
phil294

: পথ, সম্পর্কিত (এবং অনুত্তরিত) দ্বারা stackoverflow.com/questions/41124528/...
phil294

উত্তর:


180

ধরে নিই যে আপনি ES6 ব্যবহার করছেন, আপনি ব্যবহার করতে পারেন var copy = Object.assign({}, original)। আধুনিক ব্রাউজারগুলিতে কাজ করে; আপনার যদি পুরানো ব্রাউজারগুলির সমর্থন করতে হয় তবে এই পলিফিলটি দেখুন

হালনাগাদ:

টাইপস্ক্রিপ্ট ২.১+ এর সাথে, ES6 শর্টহ্যান্ড অবজেক্ট স্প্রেড নোটেশন উপলব্ধ:

const copy = { ...original }

75
নোট যা angular.copy()বিপরীতে একটি গভীর অনুলিপি তৈরি করে Object.assign()। আপনি গভীর কপি ব্যবহার lodash চান _.cloneDeep(value) lodash.com/docs#cloneDeep
bertrandg

ওয়েবস্টর্মে আমি পেয়েছি Unresolved function or method assign(); আইডিই বিশদ: ওয়েবস্টর্ম 2016.2। কীভাবে সমাধান করব?
মিহাই

2
@meorfi যাও File -> Settings -> Languages & Frameworks -> Javascriptএবং সেট Javascript language versionকরার ECMAScript 6.0
Siri0S

@bertrandg _.clone (মান) angular.copy () চেয়ে ভিন্ন, এটা নতুন দৃষ্টান্ত তৈরি করবে না, তাই হিসাবে _.cloneDeep (মান) এটি এখনও একটি রেফারেন্স তৈরি stackoverflow.com/questions/26411754/...
Zealitude

5
অতিরিক্ত হিসাবে, আপনি যদি একটি অ্যারে অনুলিপি করেন তবে ব্যবহার করুন:const copy = [ ...original ]
ডেলিজেম

43

আমাদের আরও ভাল সমাধান না হওয়া পর্যন্ত আপনি নিম্নলিখিতটি ব্যবহার করতে পারেন:

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

সম্পাদনা: স্পষ্টকরণ

দয়া করে নোট করুন: উপরের সমাধানটি কেবলমাত্র একটি দ্রুত সমাধানের উদ্দেশ্যে বোঝানো হয়েছিল, যখন কৌণিক 2 সক্রিয় বিকাশের অধীনে ছিল এমন সময়ে সরবরাহ করা হয়েছিল। আমার আশা ছিল আমরা শেষ পর্যন্ত একটি সমতুল্য পেতে পারি angular.copy()। অতএব আমি একটি গভীর-ক্লোনিং লাইব্রেরি লিখতে বা আমদানি করতে চাইনি।

এই পদ্ধতিতে পার্সিং তারিখের বৈশিষ্ট্যগুলির সাথেও সমস্যা রয়েছে (এটি একটি স্ট্রিং হয়ে যাবে)।

দয়া করে উত্পাদন অ্যাপ্লিকেশনগুলিতে এই পদ্ধতিটি ব্যবহার করবেন না । এটি কেবলমাত্র আপনার পরীক্ষামূলক প্রকল্পগুলিতে ব্যবহার করুন - কৌনিক 2 শেখার জন্য আপনি যা করছেন।


11
এটি আপনার তারিখগুলি নষ্ট করে দেয় এবং নরকের মতো ধীর হয়।
ল্যান্ডারভি

5
কোনও কাজ করার জন্য একটি পুরো লাইব্রেরি আমদানি করার মতো ধীর নয়, যতক্ষণ আপনি যা করছেন তা খুব সহজ ...
ইয়ান বেলচার

1
এটি ভয়াবহ, কখনই এটি ব্যবহার করবেন না
মুরহফ সওসালি

1
@ মুরহফসৌসলি দয়া করে এই উত্তরের প্রসঙ্গটি বোঝার চেষ্টা করুন। এঙ্গুলার 2 যখন বিকাশের অধীনে ছিল তখন এটি সরবরাহ করা হয়েছিল এবং আশা ছিল আমরা শেষ পর্যন্ত কৌণিক কোডপি () ফাংশনের সমতুল্য হব। অপেক্ষার সময়সীমাটি সীমাবদ্ধ করতে, আমাদের আরও ভাল সমাধান না হওয়া পর্যন্ত আমি এই সমাধানটি একটি অস্থায়ী বিকল্প হিসাবে রেখেছি। এটি গভীর ক্লোনিং সহ এক-লাইনার। এটি ভয়াবহ , আমি সম্মত ... তবে সেই সময় পরীক্ষামূলক প্রসঙ্গে, এটি খুব খারাপ নয়।
মণি

1
@ লাজারলজুবেনভিভি অবশ্যই 2018 এর ক্ষেত্রে এটি হ'ল এবং আমি আজ আপনার সাথে পুরোপুরি একমত , কিন্তু ২০১ 2016 সালে ওয়েবপ্যাকটিতে গাছ কাঁপানো হয়নি তাই আপনি বেশিরভাগ ক্ষেত্রেই একটি সম্পূর্ণ লাইব্রেরি আমদানি করবেন।
ইয়ান বেলচার

22

ভিতরে নেস্টেড অবজেক্ট থাকা গভীর অনুলিপি করার বিকল্প হ'ল লোডাশের ক্লোনডিপ পদ্ধতি ব্যবহার করে।

কৌণিকের জন্য, আপনি এটি এটি করতে পারেন:

yarn add lodashবা এর সাথে লড্যাশ ইনস্টল করুন npm install lodash

আপনার উপাদানগুলিতে, আমদানি করুন cloneDeepএবং এটি ব্যবহার করুন:

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

এটি আপনার বিল্ডে কেবল 18 কেবি যুক্ত হয়েছে, সুবিধার জন্য উপযুক্ত।

আমি এখানে একটি নিবন্ধও লিখেছি , যদি আপনার লড্যাশের ক্লোনডিপ ব্যবহারের বিষয়ে আরও অন্তর্দৃষ্টি প্রয়োজন।


2
"কেবলমাত্র 18 কেবি" আউটপুটটিতে যুক্ত হয়েছে কেবল অনুলিপি অবজেক্টগুলিতে সক্ষম হতে? জাভাস্ক্রিপ্ট একটি জগাখিচুড়ি।
এন্ডারজু

আপনার রেফারেন্সকৃত নিবন্ধটি পড়ার পরে, আমি 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

আপনি যদি কোনও শ্রেণীর উদাহরণ অনুলিপি করতে চান তবে আপনি অবজেক্ট.সেসাইনও ব্যবহার করতে পারেন তবে আপনাকে প্রথম প্যারামিটার হিসাবে একটি নতুন উদাহরণ পাস করতে হবে (instead} এর পরিবর্তে):

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

এবং তারপরে এটি আপনার টিএস ফাইলে আমদানি করুন:

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
// তারিখগুলি লিঙ্কমুক্ত করতে আমরা যুক্ত করতে পারি: যদি (অবজেক্ট.প্রোটোটাইপ.টোস্ট্রিং। কল (আপত্তি) === '[অবজেক্টের তারিখ]') new নতুন তারিখ ফিরিয়ে দিন (اعتراض.জেটটাইম ()); }
এ_জে

1
অথবা উদাহরণের প্রকারের সাহায্যে তারিখটি পরীক্ষা করুন - যদি (তারিখের আগে উদাহরণ)) নতুন তারিখ ফেরান (اعتراض.জেটটাইম ()) An
আনুপ আইজাক

0

আমার এই বৈশিষ্ট্যটি কেবলমাত্র আমার অ্যাপ্লিকেশনটির 'মডেলগুলি' তৈরি করা উচিত (কাঁচা ব্যাকএন্ড ডেটা অবজেক্টে রূপান্তরিত)। সুতরাং আমি একটি সংমিশ্রণ ব্যবহার করে শেষ অবজেক্ট.ক্রিয়েট (নির্দিষ্ট প্রোটোটাইপ থেকে নতুন বস্তু তৈরি করুন) এবং অবজেক্ট.সেসাইন (বস্তুর মধ্যে বৈশিষ্ট্য অনুলিপি )ডিপ কপিটি ম্যানুয়ালি হ্যান্ডেল করা দরকার। আমি এই জন্য একটি টুকরো তৈরি ।


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

আমি কৌণিক 5 বা angular.copy ()ততোধিকের সাথে ব্যবহারের জন্য একটি পরিষেবা তৈরি করেছি, এটি কৌণিকের বেস ব্যবহার করে , এটি আমার পক্ষে ভাল কাজ করে। অতিরিক্তভাবে যেমন অন্যান্য ফাংশন রয়েছে 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()পদ্ধতি জাভাস্ক্রিপ্ট অবজেক্ট বা JSON স্ট্রিংকে মান পরিবর্তন করে


2
এটি ইতিমধ্যে উপরে নিঃসন্দেহে বলা হয়েছে যে এটির চিকিত্সা করার এটিই সবচেয়ে খারাপ উপায়!
আলেসান্দ্রো

0

আপনি অ্যারের মত ক্লোন করতে পারেন

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

এবং বস্তুর মতো ক্লোন করুন

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

0

আপনি যদি ইতিমধ্যে লোডাশ ব্যবহার না করে থাকেন তবে আমি কেবলমাত্র এই একটি পদ্ধতির জন্য এটি ইনস্টল করার পরামর্শ দেব না। আমি পরিবর্তে আরও সংকীর্ণ বিশেষায়িত লাইব্রেরি যেমন 'ক্লোন' এর পরামর্শ দিই:

npm install clone
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.