জাভাস্ক্রিপ্টে কোনও বিষয় গভীরভাবে ক্লোন করার সবচেয়ে কার্যকর উপায় কী?


5180

একটি জাভাস্ক্রিপ্ট অবজেক্ট ক্লোন করার সবচেয়ে কার্যকর উপায় কি? আমি ব্যবহার obj = eval(uneval(o));হতে দেখেছি , তবে এটি অ-মানক এবং কেবল ফায়ারফক্স দ্বারা সমর্থিত

আমি মতো কাজগুলি করেছি obj = JSON.parse(JSON.stringify(o));তবে দক্ষতার বিষয়ে প্রশ্ন করি।

আমি বিভিন্ন ত্রুটিগুলি নিয়ে পুনরাবৃত্তির অনুলিপি ফাংশনগুলিও দেখেছি।
আমি আশ্চর্য হয়েছি যে কোনও আধ্যাত্মিক সমাধান নেই।


566
ইভাল মন্দ নয়। খারাপভাবে খারাপ ব্যবহার করা হয়। যদি আপনি এর পার্শ্ব প্রতিক্রিয়াগুলি সম্পর্কে ভয় পান তবে আপনি এটি ভুল ব্যবহার করছেন। আপনি যে পার্শ্ব প্রতিক্রিয়াগুলির আশঙ্কা করছেন তা হ'ল এটি ব্যবহারের কারণ। আসলে যেভাবে কেউ আপনার প্রশ্নের উত্তর দিয়েছে?
জেমস

15
ক্লোনিং অবজেক্টস একটি কৌশলযুক্ত ব্যবসা, বিশেষত স্বেচ্ছাসেবী সংগ্রহের কাস্টম অবজেক্টগুলির সাথে। এটি সম্ভবত কোনও উপায় নেই কেন এটি করার উপায়।
বি01

12
eval()সাধারণত একটি খারাপ ধারণা কারণ অনেক জাভাস্ক্রিপ্ট ইঞ্জিনের অপটিমাইজারদের মাধ্যমে সেট করা ভেরিয়েবলগুলির সাথে কাজ করার সময় বন্ধ করতে হয়eval । শুধু eval()আপনার কোড থাকা খারাপ কর্মক্ষমতা হতে পারে।
user56reinstatemonica8


12
নোট করুন যে JSONপদ্ধতিটি জাভাস্ক্রিপ্টের যে কোনও ধরণের JSON- তে সমান নয় loose উদাহরণস্বরূপ: JSON.parse(JSON.stringify({a:null,b:NaN,c:Infinity,d:undefined,e:function(){},f:Number,g:false}))উত্পাদিত হবে{a: null, b: null, c: null, g: false}
অরিয়াদাম

উত্তর:


4727

নেটিভ ডিপ ক্লোনিং

একে "স্ট্রাকচার্ড ক্লোনিং" বলা হয়, নোড 11 এবং তারপরে পরীক্ষামূলকভাবে কাজ করে এবং আশা করি ব্রাউজারগুলিতে নেমে আসবে। আরও তথ্যের জন্য এই উত্তর দেখুন ।

ডেটা ক্ষতি সহ দ্রুত ক্লোনিং - JSON.parse / স্ট্রিংফাই

আপনি ব্যবহার না করেন তাহলে Dateএস, ফাংশন, undefined, Infinity, RegExps, মানচিত্র, সেট, ব্লব, FileLists, ImageDatas, বিক্ষিপ্ত অ্যারেগুলির টাইপ বিন্যাস বা আপনার বস্তুর মধ্যে অন্যান্য জটিল ধরনের, গভীর ক্লোন করার জন্য একটি খুব সহজ এক মাছ ধরার নৌকা একটি বস্তু হল:

JSON.parse(JSON.stringify(object))

const a = {
  string: 'string',
  number: 123,
  bool: false,
  nul: null,
  date: new Date(),  // stringified
  undef: undefined,  // lost
  inf: Infinity,  // forced to 'null'
  re: /.*/,  // lost
}
console.log(a);
console.log(typeof a.date);  // Date object
const clone = JSON.parse(JSON.stringify(a));
console.log(clone);
console.log(typeof clone.date);  // result of .toISOString()

দেখুন Corban এর উত্তর জন্য ।

একটি লাইব্রেরি ব্যবহার করে নির্ভরযোগ্য ক্লোনিং

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

  • লোডাশ - cloneDeep; লড্যাশক্লোনডিপের মাধ্যমে আলাদাভাবে আমদানি করা যায় মডিউলের এবং যদি আপনি ইতিমধ্যে একটি গভীর ক্লোনিং ফাংশন সরবরাহ করে এমন কোনও লাইব্রেরি ব্যবহার করছেন না তবে সম্ভবত এটি আপনার সেরা পছন্দ is
  • কৌণিক জেএস - angular.copy
  • jQuery - jQuery.extend(true, { }, oldObject); .clone()শুধুমাত্র ডোম উপাদানগুলিকে ক্লোন করে

ES6

সম্পূর্ণতার জন্য, নোট করুন যে ES6 দুটি অগভীর অনুলিপি প্রক্রিয়া সরবরাহ করে: Object.assign()এবং স্প্রেড সিনট্যাক্স । যা সমস্ত গণনাকারী নিজস্ব বৈশিষ্ট্যের মানগুলি একটি বস্তু থেকে অন্য বস্তুতে অনুলিপি করে। উদাহরণ স্বরূপ:

var A1 = {a: "2"};
var A2 = Object.assign({}, A1);
var A3 = {...A1};  // Spread Syntax

7
@ থিফমাস্টার github.com/jquery/jquery/blob/master/src/core.js লাইন ২ line6- তে (এখানে কিছুটা কোড রয়েছে যা " জেএসে এটি কীভাবে করা যায়" এর কোডটি এখানে রয়েছে :)
রুন এফএস

7
আগ্রহীদের জন্য jQuery গভীর কপির পিছনে জেএস কোড এখানে রয়েছে: github.com/jquery/jquery/blob/master/src/core.js#L265-327
অ্যালেক্স ডব্লু

194
ওহো! কেবলমাত্র পরিষ্কার-পরিচ্ছন্ন হওয়ার জন্য: কেন এই প্রতিক্রিয়াটিকে সঠিক উত্তর হিসাবে বেছে নেওয়া হয়েছিল তা ধারণা নেই, এটি নীচে দেওয়া প্রতিক্রিয়াগুলির একটি জবাব ছিল: স্ট্যাকওভারফ্লো.com/ a/ 122190 / 6524 (যা প্রস্তাব দিচ্ছিল.clone() , যা সঠিক কোড নয়) এই প্রসঙ্গে ব্যবহার করে)। দুর্ভাগ্যক্রমে এই প্রশ্নটি এত সংশোধন করে গেছে মূল আলোচনাটি এখন আর স্পষ্ট নয়! আপনি গতির যত্ন নিলে দয়া করে কেবল কার্বনের পরামর্শ অনুসরণ করুন এবং একটি লুপ লিখুন বা বৈশিষ্ট্যগুলি সরাসরি কোনও নতুন অবজেক্টে অনুলিপি করুন। অথবা এটি নিজের জন্য পরীক্ষা করে দেখুন!
জন রেসিগ

9
এটি একটি জাভাস্ক্রিপ্ট প্রশ্ন (jQuery এর উল্লেখ নেই)।
gphilip

60
কেউ jQuery ব্যবহার না করে কীভাবে এটি করবে?
অসাধারণতা

2263

এই মানদণ্ডটি চেকআউট করুন: http://jsben.ch/#/bWfk9

আমার আগের পরীক্ষাগুলিতে যেখানে গতি ছিল আমার প্রধান উদ্বেগ I

JSON.parse(JSON.stringify(obj))

কোনও বস্তুর গভীর ক্লোন করার সবচেয়ে ধীরতম উপায় হতে হবে ( 10-10% দ্বারা সত্য সেট করা পতাকা সহ jQuery.extend এর চেয়ে ধীর deep)।

deepপতাকাটি false(অগভীর ক্লোন) সেট করা থাকলে jQuery.extend খুব দ্রুত tend এটি একটি ভাল বিকল্প, কারণ এটিতে বৈধতা যাচাইয়ের জন্য কিছু অতিরিক্ত যুক্তি অন্তর্ভুক্ত এবং অপরিজ্ঞাত বৈশিষ্ট্য ইত্যাদির উপর অনুলিপি করে না তবে এটি আপনাকে কিছুটা কমিয়ে দেবে।

আপনি যদি ক্লোন করার চেষ্টা করছেন এমন অবজেক্টগুলির কাঠামো জানেন বা গভীর নেস্টেড অ্যারেগুলি এড়াতে পারেন for (var i in obj)তবে hasnwanProperty চেক করার সময় আপনি নিজের অবজেক্টটি ক্লোন করতে একটি সাধারণ লুপ লিখতে পারেন এবং এটি jQuery এর চেয়ে অনেক দ্রুত হবে।

শেষ অবধি যদি আপনি একটি গরম লুপে কোনও পরিচিত অবজেক্ট স্ট্রাকচার ক্লোন করার চেষ্টা করছেন আপনি ক্লোন পদ্ধতিটি কেবল আস্তর করে এবং বস্তুটি ম্যানুয়ালি তৈরি করে আরও বেশি পারফরম্যান্স পেতে পারেন।

জাভাস্ক্রিপ্ট ট্রেস ইঞ্জিনগুলি for..inলুপগুলি অনুকূল করে এবং হ্যাঁউনপ্রপার্টি চেক করার ক্ষেত্রে স্তন্যপান করে তবে আপনাকে ধীর করে দেবে। গতি একটি পরম প্রয়োজন যখন ম্যানুয়াল ক্লোন।

var clonedObject = {
  knownProp: obj.knownProp,
  ..
}

বস্তুগুলিতে JSON.parse(JSON.stringify(obj))পদ্ধতিটি ব্যবহার করে সাবধান থাকুন Date- JSON.stringify(new Date())আইএসও ফর্ম্যাটে তারিখের একটি স্ট্রিং প্রতিনিধিত্ব প্রদান করে, যা JSON.parse() কোনওDate বস্তুতে ফিরে রূপান্তর করে নাআরও তথ্যের জন্য এই উত্তর দেখুন

অতিরিক্ত হিসাবে, দয়া করে নোট করুন যে, ক্রোম 65 এ কমপক্ষে, নেটিভ ক্লোনিং করার উপায় নয়। জেএসপিফার মতে, নতুন ফাংশন তৈরি করে নেটিভ ক্লোনিং করা JSON.stringify ব্যবহারের চেয়ে প্রায় 800x ধীর গতিপথ যা পুরো বোর্ড জুড়ে অবিশ্বাস্যভাবে দ্রুত is

ES6 এর জন্য আপডেট

আপনি যদি জাভাস্ক্রিপ্ট ES6 ব্যবহার করছেন তবে ক্লোনিং বা অগভীর অনুলিপির জন্য এই স্থানীয় পদ্ধতিটি ব্যবহার করে দেখুন।

Object.assign({}, obj);

4
@ ট্রিসিস অবজেক্ট.ক্রেইট অবজেক্টটি ক্লোন করছে না, প্রোটোটাইপ অবজেক্ট ব্যবহার করছে ... jsfiddle.net/rahpuser/yufzc1jt/2
rahpuser

105
এই পদ্ধতিটি keysআপনার থেকেও মুছে ফেলবে object, যার functionsমান হিসাবে রয়েছে, কারণ JSONকার্যকারিতা সমর্থন করে না।
কার্লেন কিশমিরিয়ান

39
এছাড়াও মনে রাখবেন যে ব্যবহার JSON.parse(JSON.stringify(obj))তারিখ বস্তুর উপর এছাড়াও তারিখ ফিরে রূপান্তর করবে ইউটিসি মধ্যে স্ট্রিং প্রতিনিধিত্ব ISO8601 বিন্যাস।
dnlgmzddr

31
জেএসওএন পদ্ধতির সাথে বিজ্ঞপ্তি সংক্রান্ত রেফারেন্সগুলিও বন্ধ হয়ে যায়।
সমৃদ্ধ পুনরায়

28
@ বিলোপ, অবজেক্ট.স্যাসাইন ({} ,জেজটোক্লোন) মনে হচ্ছে এটি অগভীর ক্লোন করে যদিও - ডিভাইস কনসোলের চারপাশে খেলতে গিয়ে অবজেক্ট ক্লোনটি এখনও ক্লোনযুক্ত বস্তুর একটি রেফারেন্স নির্দেশ করে। সুতরাং আমি মনে করি না এটি এখানে সত্যিই প্রযোজ্য।
গ্যারেট সিম্পসন

473

ধরে নিই যে আপনার কেবলমাত্র ভেরিয়েবল রয়েছে এবং আপনার অবজেক্টে কোনও ফাংশন নেই, আপনি কেবল ব্যবহার করতে পারেন:

var newObject = JSON.parse(JSON.stringify(oldObject));

86
আমি এই সন্ধানটি যেমনটি পেয়েছি ঠিক তেমনটিই যদি আপনার অবজেক্টের কোনও ফাংশন থাকে (আমার অভ্যন্তরীণ গেটারস এবং সেটটার রয়েছে) তবে স্ট্রাইন্ডিং করার পরে এগুলি হারিয়ে যায় .. যদি আপনার এই পদ্ধতির দরকার হয় তবে তা ঠিক আছে ..
মার্কিভ

31
@ জেসন, এই পদ্ধতিটি অগভীর অনুলিপি (একটি গভীর বস্তুর উপর) চেয়ে ধীর হওয়ার কারণ হ'ল এই পদ্ধতিটি, সংজ্ঞা অনুসারে, গভীর অনুলিপিগুলি। তবে যেহেতু JSONনেটিভ কোডে প্রয়োগ করা হয়েছে (বেশিরভাগ ব্রাউজারগুলিতে) এটি অন্য কোনও জাভাস্ক্রিপ্ট-ভিত্তিক গভীর অনুলিপি সমাধানের চেয়ে যথেষ্ট দ্রুত হবে এবং কখনও কখনও জাভাস্ক্রিপ্ট-ভিত্তিক অগভীর অনুলিপি করার কৌশলটির চেয়েও দ্রুত হতে পারে (দেখুন: jsperf.com/cloning -আন-অবজেক্ট / 79 )।
মিজিন

35
JSON.stringify({key: undefined}) //=> "{}"
ওয়েব_ডিজাইনার

32
এই কৌশলটি Dateবস্তুর অভ্যন্তরে সঞ্চিত সমস্ত বস্তুগুলিকেও স্ট্রিং ফর্মে রূপান্তরিত করে ধ্বংস করতে চলেছে ।
fstab

13
এটি JSON
স্পেসের

396

স্ট্রাকচার্ড ক্লোনিং

এইচটিএমএল স্ট্যান্ডার্ডটিতে একটি অভ্যন্তরীণ কাঠামোগত ক্লোনিং / সিরিয়ালাইজেশন অ্যালগরিদম অন্তর্ভুক্ত যা বস্তুর গভীর ক্লোন তৈরি করতে পারে। এটি এখনও কিছু অন্তর্নির্মিত প্রকারের মধ্যেই সীমাবদ্ধ, তবে জেএসওএন সমর্থিত কয়েকটি প্রকারের পাশাপাশি এটি তারিখ, রেজিএক্স্পস, মানচিত্র, সেটস, ব্লবস, ফাইললিস্টস, ইমেজড্যাটাস, স্পারস অ্যারে, টাইপড অ্যারে এবং সম্ভবত ভবিষ্যতে আরও অনেক কিছু সমর্থন করে । এটি ক্লোনযুক্ত ডেটাতে রেফারেন্সগুলি সংরক্ষণ করে, এটি চক্রীয় এবং পুনরাবৃত্ত কাঠামোগুলি সমর্থন করে যাতে জেএসএনের জন্য ত্রুটি ঘটায়।

নোড.জেজে সমর্থন: পরীক্ষামূলক 🙂

v8নোড.জেএস- এ মডিউল বর্তমানে (নোড 11 হিসাবে) সরাসরি কাঠামোগত সিরিয়ালাইজেশন এপিআই প্রকাশ করেছে তবে এই কার্যকারিতাটি এখনও "পরীক্ষামূলক" হিসাবে চিহ্নিত হয়েছে এবং ভবিষ্যতের সংস্করণগুলিতে পরিবর্তন বা অপসারণের বিষয় হিসাবে চিহ্নিত। আপনি যদি কোনও সামঞ্জস্যপূর্ণ সংস্করণ ব্যবহার করেন তবে কোনও অবজেক্টের ক্লোনিং করা এতটাই সহজ:

const v8 = require('v8');

const structuredClone = obj => {
  return v8.deserialize(v8.serialize(obj));
};

ব্রাউজারগুলিতে সরাসরি সমর্থন: সম্ভবত শেষ পর্যন্ত? 😐

ব্রাউজারগুলি বর্তমানে কাঠামোগত ক্লোনিং অ্যালগরিদমের জন্য সরাসরি ইন্টারফেস সরবরাহ করে না, তবে গিটহাবের হোয়াইটএইচজিএইচটিএমএল # 793 এ একটি বিশ্বব্যাপী structuredClone()ফাংশন নিয়ে আলোচনা করা হয়েছে । বর্তমানে প্রস্তাবিত হিসাবে, বেশিরভাগ উদ্দেশ্যে এটি ব্যবহার করা যেমন সহজ হবে:

const clone = structuredClone(original);

এটি পাঠানো না হলে, ব্রাউজারগুলির কাঠামোগত ক্লোন প্রয়োগগুলি কেবল পরোক্ষভাবেই প্রকাশিত হয়।

অ্যাসিঙ্ক্রোনাস ওয়ার্কারআউন্ড: ব্যবহারযোগ্য। 😕

বিদ্যমান এপিআইগুলির সাথে একটি কাঠামোগত ক্লোন তৈরির নিম্ন-ওভারহেড উপায়টি একটি বার্তা চ্যানেলের একটি পোর্টের মাধ্যমে ডেটা পোস্ট করা । অন্য বন্দরটি সংযুক্তের messageকাঠামোগত ক্লোন সহ একটি ইভেন্ট নির্গত করবে .data। দুর্ভাগ্যক্রমে, এই ইভেন্টগুলির জন্য শোনা অগত্যা অ্যাসিনক্রোনাস এবং সিঙ্ক্রোনাস বিকল্পগুলি কম ব্যবহারিক।

class StructuredCloner {
  constructor() {
    this.pendingClones_ = new Map();
    this.nextKey_ = 0;

    const channel = new MessageChannel();
    this.inPort_ = channel.port1;
    this.outPort_ = channel.port2;

    this.outPort_.onmessage = ({data: {key, value}}) => {
      const resolve = this.pendingClones_.get(key);
      resolve(value);
      this.pendingClones_.delete(key);
    };
    this.outPort_.start();
  }

  cloneAsync(value) {
    return new Promise(resolve => {
      const key = this.nextKey_++;
      this.pendingClones_.set(key, resolve);
      this.inPort_.postMessage({key, value});
    });
  }
}

const structuredCloneAsync = window.structuredCloneAsync =
    StructuredCloner.prototype.cloneAsync.bind(new StructuredCloner);

উদাহরণ ব্যবহার:

const main = async () => {
  const original = { date: new Date(), number: Math.random() };
  original.self = original;

  const clone = await structuredCloneAsync(original);

  // They're different objects:
  console.assert(original !== clone);
  console.assert(original.date !== clone.date);

  // They're cyclical:
  console.assert(original.self === original);
  console.assert(clone.self === clone);

  // They contain equivalent values:
  console.assert(original.number === clone.number);
  console.assert(Number(original.date) === Number(clone.date));

  console.log("Assertions complete.");
};

main();

সিঙ্ক্রোনাস ওয়ার্কারাউন্ডস: ভয়াবহ! 🤢

সুসংগতভাবে কাঠামোগত ক্লোন তৈরি করার জন্য কোনও ভাল বিকল্প নেই। পরিবর্তে অবৈধ হ্যাক একটি দম্পতি এখানে।

history.pushState()এবং history.replaceState()উভয়ই তাদের প্রথম যুক্তির একটি কাঠামোগত ক্লোন তৈরি করে এবং সেই মানটিকে নির্ধারিত করে history.state। আপনি এটির মতো যেকোন বস্তুর কাঠামোগত ক্লোন তৈরি করতে এটি ব্যবহার করতে পারেন:

const structuredClone = obj => {
  const oldState = history.state;
  history.replaceState(obj, null);
  const clonedObj = history.state;
  history.replaceState(oldState, null);
  return clonedObj;
};

উদাহরণ ব্যবহার:

সিঙ্ক্রোনাস হলেও এটি অত্যন্ত ধীর হতে পারে। এটি ব্রাউজারের ইতিহাসের কারসাজির সাথে সম্পর্কিত সমস্ত ওভারহেডকে অন্তর্ভুক্ত করে। এই পদ্ধতিটি বারবার কল করার ফলে ক্রোম সাময়িকভাবে প্রতিক্রিয়াহীন হয়ে উঠতে পারে।

Notificationকন্সট্রাকটর তার সংশ্লিষ্ট ডেটার গঠিত ক্লোন তৈরি করে। এটি ব্যবহারকারীর কাছে একটি ব্রাউজার বিজ্ঞপ্তি প্রদর্শন করার চেষ্টাও করে, তবে আপনি নোটিফিকেশন অনুমতির অনুরোধ না করা পর্যন্ত এটি নিঃশব্দে ব্যর্থ হবে। যদি অন্য উদ্দেশ্যে আপনার অনুমতি থাকে, আমরা তত্ক্ষণাত আমাদের তৈরি বিজ্ঞপ্তিটি বন্ধ করব।

const structuredClone = obj => {
  const n = new Notification('', {data: obj, silent: true});
  n.onshow = n.close.bind(n);
  return n.data;
};

উদাহরণ ব্যবহার:


3
@ অরিনাঃ আমি কেবল আবার অনুমানটি দেখেছি এবং আপনি ঠিক বলেছেন: পদ্ধতিগুলি history.pushState()এবং history.replaceState()পদ্ধতিগুলি উভয় সিঙ্ক্রোনালি history.stateতাদের প্রথম যুক্তির কাঠামোযুক্ত কাঠামোতে সেট করে। কিছুটা অদ্ভুত, তবে এটি কাজ করে। আমি এখন আমার উত্তর আপডেট করছি।
জেরেমি ব্যাংকগুলি

40
এটা ঠিক এত ভুল! সেই এপিআইটি এইভাবে ব্যবহার করার উদ্দেশ্যে নয়।
ফারদিন কে।

209
ফায়ারফক্সে পুশস্টেট প্রয়োগকারী লোক হিসাবে, আমি এই হ্যাকটিতে অদ্ভুত গর্ব এবং বিদ্রোহের মিশ্রণ অনুভব করি। ভালো করছো সকলে.
জাস্টিন এল।

পুশস্টেট বা বিজ্ঞপ্তি হ্যাক কিছু বস্তুর জন্য যেমন ফাংশনটির জন্য কাজ করে না
শিশির অরোরা

323

যদি কোনও বিল্টিন না থাকে তবে আপনি চেষ্টা করতে পারেন:

function clone(obj) {
    if (obj === null || typeof (obj) !== 'object' || 'isActiveClone' in obj)
        return obj;

    if (obj instanceof Date)
        var temp = new obj.constructor(); //or new Date(obj);
    else
        var temp = obj.constructor();

    for (var key in obj) {
        if (Object.prototype.hasOwnProperty.call(obj, key)) {
            obj['isActiveClone'] = null;
            temp[key] = clone(obj[key]);
            delete obj['isActiveClone'];
        }
    }
    return temp;
}

20
জিকুয়েরি সলিউশনটি ডোম উপাদানগুলির জন্য কাজ করবে তবে কেবল কোনও অবজেক্ট নয়। মটুলগুলির একই সীমা রয়েছে। কাশফুল যে কোনও বস্তুর জন্য একটি জেনেরিক "ক্লোন" থাকুক ... পুনরাবৃত্ত সমাধানটি যে কোনও কিছুর জন্য কাজ করা উচিত। এটি সম্ভবত যাওয়ার উপায়।
jschrab

5
ক্লোন করা অবজেক্টটির কোনও কনস্ট্রাক্টর রয়েছে যার জন্য পরামিতিগুলির প্রয়োজন হয় এই ফাংশনটি বিরতি। দেখে মনে হচ্ছে আমরা এটিকে "var টেম্প = নতুন অবজেক্ট ()" এ পরিবর্তন করতে পারি এবং এটি প্রতিটি ক্ষেত্রে কাজ করতে পারে, না?
অ্যান্ড্রু আর্নট

3
অ্যান্ড্রু, আপনি যদি এটিকে ভার্চ টেম্প = নতুন অবজেক্ট () এ পরিবর্তন করেন তবে আপনার ক্লোনটির মূল অবজেক্টের মতো একই প্রোটোটাইপ থাকবে না। ব্যবহার করে দেখুন: 'var newProto = ফাংশন () {}; newProto.prototype = obj.constructor; var temp = নতুন নতুনপ্রোটো (); '
লিমস্কোডার

1
লিমস্কোডার এর উত্তরের অনুরূপ, কনস্ট্রাক্টরকে কল না করে কীভাবে এটি করবেন সে সম্পর্কে আমার উত্তরটি দেখুন: stackoverflow.com/a/13333781/560114
ম্যাট ব্রাউন

3
উপ-অংশগুলির (যেমন, অবজেক্টের নেটওয়ার্ক) রেফারেন্স যুক্ত বস্তুর জন্য, এটি কাজ করে না: দুটি রেফারেন্স একই সাব-অবজেক্টের দিকে নির্দেশ করলে, অনুলিপিতে এর দুটি পৃথক অনুলিপি থাকে। এবং যদি পুনরাবৃত্ত তথ্যসূত্র থাকে তবে ফাংশনটি কখনই শেষ হবে না (ভাল, কমপক্ষে আপনি যেভাবে চান সেটি তেমন নয় :-)) এই সাধারণ ক্ষেত্রে আপনাকে ইতিমধ্যে অনুলিপি করা বস্তুর একটি অভিধান যুক্ত করতে হবে এবং আপনি এটি ইতিমধ্যে অনুলিপি করেছেন কিনা তা পরীক্ষা করে দেখুন ... আপনি যখন কোনও সাধারণ ভাষা ব্যবহার করেন তখন প্রোগ্রামিং জটিল হয়
1313

153

কোডের এক লাইনে কোনও বস্তুকে ক্লোন করার (ডিপ-ক্লোন নয়) দক্ষ উপায়

একটি Object.assignপদ্ধতি ECMAScript 2015 (ES6) স্ট্যান্ডার্ডের একটি অংশ এবং আপনার যা প্রয়োজন ঠিক তা করে।

var clone = Object.assign({}, obj);

অবজেক্ট.সেসাইন () পদ্ধতিটি এক বা একাধিক উত্স অবজেক্ট থেকে একটি লক্ষ্য অবজেক্টে সমস্ত পরিগণিত নিজস্ব সম্পত্তিগুলির মানগুলি অনুলিপি করতে ব্যবহৃত হয়।

আরও পড়ুন ...

Polyfill পুরোনো ব্রাউজারে সমর্থন করার জন্য:

if (!Object.assign) {
  Object.defineProperty(Object, 'assign', {
    enumerable: false,
    configurable: true,
    writable: true,
    value: function(target) {
      'use strict';
      if (target === undefined || target === null) {
        throw new TypeError('Cannot convert first argument to object');
      }

      var to = Object(target);
      for (var i = 1; i < arguments.length; i++) {
        var nextSource = arguments[i];
        if (nextSource === undefined || nextSource === null) {
          continue;
        }
        nextSource = Object(nextSource);

        var keysArray = Object.keys(nextSource);
        for (var nextIndex = 0, len = keysArray.length; nextIndex < len; nextIndex++) {
          var nextKey = keysArray[nextIndex];
          var desc = Object.getOwnPropertyDescriptor(nextSource, nextKey);
          if (desc !== undefined && desc.enumerable) {
            to[nextKey] = nextSource[nextKey];
          }
        }
      }
      return to;
    }
  });
}

82
এটি পুনরাবৃত্তির সাথে অনুলিপি করে না তাই কোনও বস্তুর ক্লোনিংয়ের সমস্যার সমাধানের প্রস্তাব দেয় না।
এমওয়াইট

5
এই পদ্ধতিটি কার্যকর হয়েছিল, যদিও আমি কয়েকটি পরীক্ষা করেছি এবং _.Extend ({}, (Obj)) সবচেয়ে দ্রুততম ছিলাম: JSON.parse এর চেয়ে 20x দ্রুত এবং Object.assign এর চেয়ে 60% দ্রুত, উদাহরণস্বরূপ। এটি সমস্ত উপ-অবজেক্টগুলি বেশ ভালভাবে অনুলিপি করে।
নিকো

11
@ এমবাইটে ক্লোন এবং ডিপ-ক্লোনের মধ্যে পার্থক্য রয়েছে। এই উত্তরটি আসলে ক্লোন করে, তবে এটি গভীর-ক্লোন করে না।
মেরিওন হিউজেস

57
অপশন গভীর ক্লোন জন্য জিজ্ঞাসা। এটি গভীর ক্লোন করে না।
ব্যবহারকারী566245

9
এই পদ্ধতিটি শাল কপি করে , ডিপ কপি করে না ! এ কারণে এটি সম্পূর্ণ ভুল উত্তর !
ভারত

97

কোড:

// extends 'from' object with members from 'to'. If 'to' is null, a deep clone of 'from' is returned
function extend(from, to)
{
    if (from == null || typeof from != "object") return from;
    if (from.constructor != Object && from.constructor != Array) return from;
    if (from.constructor == Date || from.constructor == RegExp || from.constructor == Function ||
        from.constructor == String || from.constructor == Number || from.constructor == Boolean)
        return new from.constructor(from);

    to = to || new from.constructor();

    for (var name in from)
    {
        to[name] = typeof to[name] == "undefined" ? extend(from[name], null) : to[name];
    }

    return to;
}

টেস্ট:

var obj =
{
    date: new Date(),
    func: function(q) { return 1 + q; },
    num: 123,
    text: "asdasd",
    array: [1, "asd"],
    regex: new RegExp(/aaa/i),
    subobj:
    {
        num: 234,
        text: "asdsaD"
    }
}

var clone = extend(obj);

3
কি var obj = {}এবংobj.a = obj
নিউমউজিক

5
আমি এই ফাংশন বুঝতে পারি না। ধরুন from.constructorহয় Dateউদাহরণস্বরূপ। তৃতীয় ifপরীক্ষা কীভাবে পৌঁছে যাবে যখন দ্বিতীয় ifপরীক্ষাটি সফল হবে এবং ফাংশনটি ফিরে আসবে (যেহেতু Date != Object && Date != Array)?
অ্যাডাম ম্যাককি

1
@ অ্যাডামসকিউই কারণ জাভাস্ক্রিপ্ট আর্গুমেন্ট পাসিং এবং ভেরিয়েবল অ্যাসাইনমেন্ট জটিল । এই পদ্ধতির তারিখগুলি সহ (যা প্রকৃতপক্ষে দ্বিতীয় টেস্ট দ্বারা পরিচালিত হয়) দুর্দান্ত কাজ করে - এখানে পরীক্ষার জন্য ফিডল: jsfiddle.net/zqv9q9c6
ব্রিচিনস

1
@ নিকসুইটিং: চেষ্টা করুন - এটি কার্যকর হতে পারে। যদি তা না হয় - ঠিক করুন এবং উত্তরটি আপডেট করুন। এটি এখানে সম্প্রদায়টিতে কীভাবে কাজ করে :)
কামারে

1
এই ফাংশনটি পরীক্ষায় রেজেক্সকে ক্লোন করে না, "from.constructor! = অবজেক্ট && from.constructor! = অ্যারে" শর্তটি অন্যান্য কনস্ট্রাক্টরের ক্ষেত্রে সর্বদা সংখ্যা, তারিখ, এবং ইত্যাদির জন্য সত্য হয়।
aMarCruz

95

এটি আমি ব্যবহার করছি:

function cloneObject(obj) {
    var clone = {};
    for(var i in obj) {
        if(typeof(obj[i])=="object" && obj[i] != null)
            clone[i] = cloneObject(obj[i]);
        else
            clone[i] = obj[i];
    }
    return clone;
}

8
এটা ঠিক মনে হচ্ছে না। cloneObject({ name: null })=>{"name":{}}
নিয়াজ

13
এটি জাভাস্ক্রিপ্টে অন্য একটি বোবা জিনিসের কারণে typeof null > "object"তবে Object.keys(null) > TypeError: Requested keys of a value that is not an object.শর্তটি পরিবর্তন করুনif(typeof(obj[i])=="object" && obj[i]!=null)
ভিটিম.ইস

এই এর গণনীয় বৈশিষ্ট্য উত্তরাধিকারসূত্রে ধার্য হবে obj সরাসরি ক্লোন করা, এবং ধরে নেয় যে obj একটি প্লেইন অবজেক্ট।
রবজি

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

নাল ব্যবহার না করলে সমস্যা নেই Not
হোর্হে বুকারান

78

পারফরম্যান্স দ্বারা গভীর অনুলিপি: সেরা থেকে নিকৃষ্টতম স্থানে

  • পুনরায় নিয়োগ "" "(স্ট্রিং অ্যারে, সংখ্যা অ্যারে - কেবল)
  • স্লাইস (স্ট্রিং অ্যারে, নম্বর অ্যারে - কেবল)
  • সংঘবদ্ধকরণ (স্ট্রিং অ্যারে, সংখ্যা অ্যারে - কেবল)
  • কাস্টম ফাংশন: লুপ বা পুনরাবৃত্তির অনুলিপি
  • jQuery এর ex। প্রসারিত
  • JSON.parse (স্ট্রিং অ্যারে, সংখ্যা অ্যারে, অবজেক্ট অ্যারে - কেবল)
  • Underscore.js এর _.clone (STRING অ্যারে, সংখ্যা অ্যারে - শুধুমাত্র)
  • লো-ড্যাশ এর _ক্লোনডিপ

স্ট্রিং বা সংখ্যাগুলির একটি অ্যারে গভীরভাবে অনুলিপি করুন (এক স্তর - কোনও রেফারেন্স পয়েন্টার নেই):

যখন একটি অ্যারেতে সংখ্যা এবং স্ট্রিং থাকে - .slice (), .concat (), .splice (), অ্যাসাইনমেন্ট অপারেটর "=" এবং অ্যান্ডসোর.জেএস এর ক্লোন ফাংশন যেমন ফাংশন; অ্যারের উপাদানগুলির একটি গভীর অনুলিপি তৈরি করবে।

যেখানে পুনরায় নিয়োগের দ্রুততম পারফরম্যান্স রয়েছে:

var arr1 = ['a', 'b', 'c'];
var arr2 = arr1;
arr1 = ['a', 'b', 'c'];

এবং .স্লাইস () এর .concat (), http://jsperf.com/d નકલate-array-slice-vs-concat/3 এর চেয়ে ভাল পারফরম্যান্স রয়েছে

var arr1 = ['a', 'b', 'c'];  // Becomes arr1 = ['a', 'b', 'c']
var arr2a = arr1.slice(0);   // Becomes arr2a = ['a', 'b', 'c'] - deep copy
var arr2b = arr1.concat();   // Becomes arr2b = ['a', 'b', 'c'] - deep copy

গভীর বস্তুগুলির একটি অ্যারের অনুলিপি করুন (দুই বা ততোধিক স্তর - রেফারেন্স পয়েন্টার):

var arr1 = [{object:'a'}, {object:'b'}];

একটি কাস্টম ফাংশন লিখুন (ex। এক্সটেন্ড () বা JSON.parse এর চেয়ে দ্রুত পারফরম্যান্স রয়েছে):

function copy(o) {
   var out, v, key;
   out = Array.isArray(o) ? [] : {};
   for (key in o) {
       v = o[key];
       out[key] = (typeof v === "object" && v !== null) ? copy(v) : v;
   }
   return out;
}

copy(arr1);

তৃতীয় পক্ষের ইউটিলিটি ফাংশনগুলি ব্যবহার করুন:

$.extend(true, [], arr1); // Jquery Extend
JSON.parse(arr1);
_.cloneDeep(arr1); // Lo-dash

যেখানে jQuery এর ex। এক্সেটের আরও ভাল পারফরম্যান্স রয়েছে:


আমি কয়েকটি পরীক্ষা করেছিলাম এবং _.Etetend ({}, (Obj)) খুব দ্রুততম দ্বারা চালিত হয়েছিল: JSON.parse এর চেয়ে 20x দ্রুত এবং Object.assign এর চেয়ে 60% দ্রুত, উদাহরণস্বরূপ। এটি সমস্ত উপ-অবজেক্টগুলি বেশ ভালভাবে অনুলিপি করে।
নিকো

4
আপনার সমস্ত উদাহরণ অগভীর, এক স্তর। এটি একটি ভাল উত্তর নয়। প্রশ্নটি গভীর ক্লোনিং অর্থাৎ কমপক্ষে দুটি স্তরের বিষয়ে ছিল ।
কার্ল মরিসন

1
একটি গভীর অনুলিপি তখন হয় যখন কোনও বস্তু অন্য সামগ্রীর জন্য রেফারেন্স পয়েন্টার ব্যবহার না করে তার সম্পূর্ণতায় অনুলিপি করা হয়। "কমপক্ষে দুটি স্তরের" সহ jQuery.extend () এবং কাস্টম ফাংশন (যা পুনরাবৃত্ত হয়) এর মতো কপিরাইট ফাংশন (যেমন পুনরাবৃত্ত হয়) "বিভাগের অধীনে কৌশলগুলি objects সুতরাং, সমস্ত উদাহরণ "এক স্তরের" অনুলিপি নয়।
tfmontague

1
আমি আপনার কাস্টম অনুলিপি ফাংশন পছন্দ করি তবে আপনার নাল মানগুলি বাদ দেওয়া উচিত, অন্যথায় সমস্ত নাল মানগুলি বস্তুতে রূপান্তরিত হচ্ছে, যেমন:out[key] = (typeof v === "object" && v !== null) ? copy(v) : v;
জোসি

2
@ হোসামমুরাদ - 1 ফেব্রুয়ারি জোসি দ্বারা বাগটি ঠিক করা হয়েছিল (উপরের মন্তব্যে), এবং আমি উত্তরটি সঠিকভাবে আপডেট করতে ব্যর্থ হয়েছি। দুঃখিত যে এই বাগের ফলে আপনার কোড বেসটির রিফ্যাক্টর তৈরি হয়েছিল।
tfmontague

64
var clone = function() {
    var newObj = (this instanceof Array) ? [] : {};
    for (var i in this) {
        if (this[i] && typeof this[i] == "object") {
            newObj[i] = this[i].clone();
        }
        else
        {
            newObj[i] = this[i];
        }
    }
    return newObj;
}; 

Object.defineProperty( Object.prototype, "clone", {value: clone, enumerable: false});

ভাল উত্তর তবে এটি বিজ্ঞপ্তি সংক্রান্ত রেফারেন্সে ব্যর্থ।
লুক

59

জাভাস্ক্রিপ্টে অনুলিপি করা অবজেক্টগুলি (আমি মনে করি সেরা এবং সহজ)

1. JSON.parse ব্যবহার (JSON.stringify (অবজেক্ট));

var obj = { 
  a: 1,
  b: { 
    c: 2
  }
}
var newObj = JSON.parse(JSON.stringify(obj));
obj.b.c = 20;
console.log(obj); // { a: 1, b: { c: 20 } }
console.log(newObj); // { a: 1, b: { c: 2 } } 

2. তৈরি পদ্ধতি ব্যবহার

function cloneObject(obj) {
    var clone = {};
    for(var i in obj) {
        if(obj[i] != null &&  typeof(obj[i])=="object")
            clone[i] = cloneObject(obj[i]);
        else
            clone[i] = obj[i];
    }
    return clone;
}

var obj = { 
  a: 1,
  b: { 
    c: 2
  }
}
var newObj = cloneObject(obj);
obj.b.c = 20;

console.log(obj); // { a: 1, b: { c: 20 } }
console.log(newObj); // { a: 1, b: { c: 2 } } 

৩. লো-ড্যাশের _ক্লোনডিপ লিঙ্ক লড্যাশ ব্যবহার করা

var obj = { 
  a: 1,
  b: { 
    c: 2
  }
}

var newObj = _.cloneDeep(obj);
obj.b.c = 20;
console.log(obj); // { a: 1, b: { c: 20 } }
console.log(newObj); // { a: 1, b: { c: 2 } } 

৪. অবজেক্ট.অ্যাসাইন () পদ্ধতি ব্যবহার করা

var obj = { 
  a: 1,
  b: 2
}

var newObj = _.clone(obj);
obj.b = 20;
console.log(obj); // { a: 1, b: 20 }
console.log(newObj); // { a: 1, b: 2 }  

তবে কখন ভুল

var obj = { 
  a: 1,
  b: { 
    c: 2
  }
}

var newObj = Object.assign({}, obj);
obj.b.c = 20;
console.log(obj); // { a: 1, b: { c: 20 } }
console.log(newObj); // { a: 1, b: { c: 20 } } --> WRONG
// Note: Properties on the prototype chain and non-enumerable properties cannot be copied.

5.Using Underscore.js _.clone লিংক Underscore.js

var obj = { 
  a: 1,
  b: 2
}

var newObj = _.clone(obj);
obj.b = 20;
console.log(obj); // { a: 1, b: 20 }
console.log(newObj); // { a: 1, b: 2 }  

তবে কখন ভুল

var obj = { 
  a: 1,
  b: { 
    c: 2
  }
}

var newObj = _.cloneDeep(obj);
obj.b.c = 20;
console.log(obj); // { a: 1, b: { c: 20 } }
console.log(newObj); // { a: 1, b: { c: 20 } } --> WRONG
// (Create a shallow-copied clone of the provided plain object. Any nested objects or arrays will be copied by reference, not duplicated.)

জেএসবিএন.সিএইচ পারফরম্যান্স বেঞ্চমার্কিং খেলার মাঠ 1 ~ 3 http://jsben.ch/KVQLd পারফরম্যান্স জাভাস্ক্রিপ্টে গভীরভাবে অনুলিপি করা হচ্ছে


5
Object.assign()গভীর অনুলিপিটি সম্পাদন করে না
রায়মসনসন

1
এগুলির জন্য আপনার মানদণ্ড যুক্ত করা উচিত; এটি খুব সহায়ক হবে
jcollum

আমি যখন অ্যারে যুক্ত কোনও অবজেক্টে "তৈরি পদ্ধতি" ব্যবহার করেছি তখন আমি তার উপর পপ () বা স্প্লাইস () ব্যবহার করতে অক্ষম ছিলাম, কেন আমি বুঝতে পারছি না? let data = {title:["one", "two"]}; let tmp = cloneObject(data); tmp.title.pop();এটি নিক্ষেপ করে: TypeError: tmp.title.pop is not a function(অবশ্যই পপ () ঠিকঠাক কাজ করে do let tmp = dataতবে আমি ডেটা প্রভাবিত না করে tmp পরিবর্তন করতে পারি না)
হুগোগোগো

আরে, আপনার শেষ উদাহরণটি ভুল। আমার মতে, আপনি অবশ্যই ভুল উদাহরণের জন্য _ক্লোন এবং _ক্লোনডিপ ব্যবহার করবেন না।
কেনেনিডিজ

এই তৈরি পদ্ধতি (২) অ্যারেগুলির জন্য কাজ করবে না, তাই না?
তোয়েভো সোভেন

57

এখানে একটি লাইব্রেরি রয়েছে ("ক্লোন" নামে পরিচিত) এটি বেশ ভাল করে তোলে । এটি আমার জানা স্বেচ্ছাসেবী বিষয়গুলির সবচেয়ে সম্পূর্ণ পুনরাবৃত্ত ক্লোনিং / অনুলিপি সরবরাহ করে। এটি বিজ্ঞপ্তি সংক্রান্ত রেফারেন্সগুলিও সমর্থন করে, যা অন্যান্য উত্তরগুলির দ্বারা কভার করা হয়নি।

আপনি এটি এনপিএম এও খুঁজে পেতে পারেন । এটি ব্রাউজারের পাশাপাশি নোড.জেএস এর জন্যও ব্যবহার করা যেতে পারে

এটি কীভাবে ব্যবহার করবেন সে সম্পর্কে এখানে একটি উদাহরণ দেওয়া হল:

এটি দিয়ে ইনস্টল করুন

npm install clone

অথবা সঙ্গে এটি প্যাকেজ Ender

ender build clone [...]

আপনি সোর্স কোডটি ম্যানুয়ালিও ডাউনলোড করতে পারেন।

তারপরে আপনি এটি আপনার সোর্স কোড ব্যবহার করতে পারেন।

var clone = require('clone');

var a = { foo: { bar: 'baz' } };  // inital value of a
var b = clone(a);                 // clone a -> b
a.foo.bar = 'foo';                // change a

console.log(a);                   // { foo: { bar: 'foo' } }
console.log(b);                   // { foo: { bar: 'baz' } }

(অস্বীকৃতি: আমি গ্রন্থাগারের লেখক))


3
নির্বিচারে নেস্টেড অবজেক্টগুলিকে ক্লোনিং করার জন্য এনপিএমের ক্লোনটি আমার কাছে অমূল্য। এটি সঠিক উত্তর।
অ্যান্ডি রে

বলুন তুলনায় আপনার lib এর পারফরম্যান্স কি JSON.parse(JSON.stringify(obj))?
pkyeck

এখানে একটি লাইব্রেরি রয়েছে যা উল্লেখ করে যে দ্রুত বিকল্প রয়েছে। পরীক্ষা করা হয়নি যদিও।
pvorb

ভাল সমাধান এবং এটি বিজ্ঞপ্তিযুক্ত রেফারেন্সগুলিকে সমর্থন করে (জেএসওন পার্সের বিপরীতে)
লুক

55

Cloning জেএসে কোনও অবজেক্ট সর্বদা উদ্বেগের বিষয় ছিল তবে এটি ES6 এর আগেই ছিল, আমি নীচে জাভাস্ক্রিপ্টে কোনও বিষয় অনুলিপি করার বিভিন্ন উপায়ে তালিকাভুক্ত করেছি, কল্পনা করুন যে আপনার নীচের অবজেক্টটি রয়েছে এবং এর একটি গভীর অনুলিপি পেতে চান:

var obj = {a:1, b:2, c:3, d:4};

উত্স পরিবর্তন না করেই এই বিষয়টিকে অনুলিপি করার কয়েকটি উপায় রয়েছে:

1) ES5 +, আপনার জন্য অনুলিপি করতে একটি সাধারণ ফাংশন ব্যবহার করে:

function deepCopyObj(obj) {
    if (null == obj || "object" != typeof obj) return obj;
    if (obj instanceof Date) {
        var copy = new Date();
        copy.setTime(obj.getTime());
        return copy;
    }
    if (obj instanceof Array) {
        var copy = [];
        for (var i = 0, len = obj.length; i < len; i++) {
            copy[i] = cloneSO(obj[i]);
        }
        return copy;
    }
    if (obj instanceof Object) {
        var copy = {};
        for (var attr in obj) {
            if (obj.hasOwnProperty(attr)) copy[attr] = cloneSO(obj[attr]);
        }
        return copy;
    }
    throw new Error("Unable to copy obj this object.");
}

2) ES5 +, JSON.parse এবং JSON.stringify ব্যবহার করে।

var  deepCopyObj = JSON.parse(JSON.stringify(obj));

3) কৌণিক জে:

var  deepCopyObj = angular.copy(obj);

4) jQuery:

var deepCopyObj = jQuery.extend(true, {}, obj);

5) ইন্ডোরস্কোর এবং লোড্যাশ:

var deepCopyObj = _.cloneDeep(obj); //latest version UndescoreJs makes shallow copy

আশা করি এই সাহায্যগুলি ...


2
আন্ডারস্কোর এ ক্লোন বর্তমান সংস্করণে গভীর ক্লোন নয়
রোজেলিও

ধন্যবাদ। হ্যাঁ ইনডস্কোরের জন্য নতুন দস্তাবেজ হিসাবে ... ক্লোন_ক্লোন (বস্তু) সরবরাহিত সরল বস্তুর একটি অগভীর-অনুলিপিযুক্ত ক্লোন তৈরি করুন। কোনও নেস্টেড অবজেক্ট বা অ্যারেগুলি রেফারেন্স দ্বারা অনুলিপি করা হবে, নকল নয়। _ক্লোন ({নাম: 'মো'}); =>} নাম: 'মো'};
আলিরেজা

59
Object.assignনেই না গভীর কপি করুন। উদাহরণ: var x = { a: { b: "c" } }; var y = Object.assign({}, x); x.a.b = "d"। এটি যদি গভীর অনুলিপি y.a.bহত তবে এখনও থাকত cতবে এখন d
কেবি

8
অবজেক্ট.সেসাইন () শুধুমাত্র প্রথম স্তরের বৈশিষ্ট্যের ক্লোন করে!
হামেস

5
ক্লোনসও () ফাংশন কী?
পাস্তোরেলো

53

আমি জানি এটি একটি পুরানো পোস্ট, তবে আমি ভেবেছিলাম যে এটি পরবর্তী ব্যক্তির পক্ষে হোঁচট খাওয়ার জন্য কিছুটা সহায়ক হতে পারে।

যতক্ষণ আপনি কোনও কিছুর জন্য অবজেক্ট বরাদ্দ করবেন না এটি স্মৃতিতে কোনও রেফারেন্স বজায় রাখে না। সুতরাং আপনি অন্য অবজেক্টের মধ্যে ভাগ করতে চান এমন একটি বস্তু তৈরি করতে, আপনাকে এমন একটি কারখানা তৈরি করতে হবে:

var a = function(){
    return {
        father:'zacharias'
    };
},
b = a(),
c = a();
c.father = 'johndoe';
alert(b.father);

16
এই উত্তরটি সত্যই প্রাসঙ্গিক নয় কারণ প্রশ্নটি রয়েছে: প্রদত্ত উদাহরণ খ কীভাবে একজন অনুলিপি তৈরি করে সিটি কারখানার সম্পর্কে না জেনে বা কারখানাটি ব্যবহার করতে চাইছে না a কারখানাটি কারখানাটি ব্যবহার করতে না চাওয়ার কারণটি হ'ল ইনস্ট্যান্টেশন করার পরে খ অতিরিক্ত তথ্য (যেমন ব্যবহারকারী ইনপুট) দিয়ে শুরু করা যেতে পারে।
নোল আব্রাহামস

12
এটি সত্য যে এটি সত্যই কোনও প্রশ্নের উত্তর নয়, তবে আমি মনে করি এটি এখানে হওয়া গুরুত্বপূর্ণ কারণ আমি এখানে আসা অনেক লোককে জিজ্ঞাসা করা সত্যই জিজ্ঞাসা করা প্রশ্নটির উত্তর is
সেমিকোলন

8
দুঃখিত বন্ধুরা, আমি কেন এতগুলি আপত্তি জানি না। কোনও বস্তুর ক্লোনিং করা একটি বেশ পরিষ্কার ধারণা, আপনি অন্য কোনও বস্তু থেকে কোনও বস্তুকে শঙ্কিত করেন, এবং কারখানার প্যাটার্ন দিয়ে একটি নতুন তৈরি করার ক্ষেত্রে এর তেমন কিছু করার নেই।
খোলা

2
এটি পূর্বনির্ধারিত বস্তুর জন্য কাজ করার সময়, এই পদ্ধতিতে "ক্লোনিং" মূল বস্তুতে যুক্ত হওয়া নতুন বৈশিষ্ট্যগুলিকে স্বীকৃতি দেবে না। আপনি যদি একটি তৈরি করেন তবে এটিতে একটি নতুন সম্পত্তি যুক্ত করুন, তারপরে খ তৈরি করুন। b এর নতুন সম্পত্তি থাকবে না। মূলত কারখানার প্যাটার্নটি নতুন বৈশিষ্ট্যগুলিতে অপরিবর্তনীয়। এটি দৃষ্টান্তমূলকভাবে ক্লোনিং নয়। দেখুন: jsfiddle.net/jzumbrun/42xejnbx
জন

1
আমি মনে করি এটি ভাল পরামর্শ, সাধারণত, যেহেতু const defaultFoo = { a: { b: 123 } };আপনি ব্যবহার না করে যেতে পারেন const defaultFoo = () => ({ a: { b: 123 } };এবং আপনার সমস্যাটি সমাধান হয়ে যায়। তবে এটি আসলে প্রশ্নের উত্তর নয়। এটি পুরো উত্তর নয়, প্রশ্নে মন্তব্য হিসাবে আরও বোধগম্য হতে পারে।
জোশি কেরিবউ

48

আপনি যদি এটি ব্যবহার করছেন তবে অ্যান্ডসকোর.জেএস লাইব্রেরির ক্লোন পদ্ধতি রয়েছে।

var newObject = _.clone(oldObject);

24
লোডাশের একটি ক্লোনডিপ পদ্ধতি রয়েছে, এটি আরও গভীর করার জন্য এটি আরও একটি পরমকে সমর্থন করে: লড্যাশ ডকস ডকস
ডকস #

12
@ ওপেনাস রাজি হয়েছেন। Lodash করার আন্ডারস্কোর সাধারণত শ্রেয়
Nha

7
আমি এই এবং অন্যান্য সমস্ত উত্তরগুলি মুছে ফেলার পক্ষে যা একটি ইউটিলিটি লাইব্রেরির .clone(...)পদ্ধতির কেবলমাত্র এক-লাইন রেফারেন্স । প্রতিটি বড় লাইব্রেরি সেগুলি রাখবে এবং বারবার সংক্ষিপ্ত অ-বিশদ উত্তরগুলি বেশিরভাগ দর্শকের পক্ষে কার্যকর নয়, যারা এই নির্দিষ্ট লাইব্রেরিটি ব্যবহার করবেন না।
জেরেমি ব্যাংকগুলি

41

এখানে কনরোয়পির উত্তরের একটি সংস্করণ রয়েছে যা নির্মাণকারীর পরামিতিগুলির প্রয়োজন থাকলেও এটি কাজ করে:

//If Object.create isn't already defined, we just do the simple shim,
//without the second argument, since that's all we need here
var object_create = Object.create;
if (typeof object_create !== 'function') {
    object_create = function(o) {
        function F() {}
        F.prototype = o;
        return new F();
    };
}

function deepCopy(obj) {
    if(obj == null || typeof(obj) !== 'object'){
        return obj;
    }
    //make sure the returned object has the same prototype as the original
    var ret = object_create(obj.constructor.prototype);
    for(var key in obj){
        ret[key] = deepCopy(obj[key]);
    }
    return ret;
}

এই ফাংশনটি আমার সরল লাইব্রেরিতেও উপলব্ধ।

সম্পাদনা:

এখানে আরও শক্তিশালী সংস্করণ রয়েছে (জাস্টিন ম্যাকক্যান্ডলেসকে ধন্যবাদ এটি এখন চক্রীয় উল্লেখগুলিও সমর্থন করে):

/**
 * Deep copy an object (make copies of all its object properties, sub-properties, etc.)
 * An improved version of http://keithdevens.com/weblog/archive/2007/Jun/07/javascript.clone
 * that doesn't break if the constructor has required parameters
 * 
 * It also borrows some code from http://stackoverflow.com/a/11621004/560114
 */ 
function deepCopy(src, /* INTERNAL */ _visited, _copiesVisited) {
    if(src === null || typeof(src) !== 'object'){
        return src;
    }

    //Honor native/custom clone methods
    if(typeof src.clone == 'function'){
        return src.clone(true);
    }

    //Special cases:
    //Date
    if(src instanceof Date){
        return new Date(src.getTime());
    }
    //RegExp
    if(src instanceof RegExp){
        return new RegExp(src);
    }
    //DOM Element
    if(src.nodeType && typeof src.cloneNode == 'function'){
        return src.cloneNode(true);
    }

    // Initialize the visited objects arrays if needed.
    // This is used to detect cyclic references.
    if (_visited === undefined){
        _visited = [];
        _copiesVisited = [];
    }

    // Check if this object has already been visited
    var i, len = _visited.length;
    for (i = 0; i < len; i++) {
        // If so, get the copy we already made
        if (src === _visited[i]) {
            return _copiesVisited[i];
        }
    }

    //Array
    if (Object.prototype.toString.call(src) == '[object Array]') {
        //[].slice() by itself would soft clone
        var ret = src.slice();

        //add it to the visited array
        _visited.push(src);
        _copiesVisited.push(ret);

        var i = ret.length;
        while (i--) {
            ret[i] = deepCopy(ret[i], _visited, _copiesVisited);
        }
        return ret;
    }

    //If we've reached here, we have a regular object

    //make sure the returned object has the same prototype as the original
    var proto = (Object.getPrototypeOf ? Object.getPrototypeOf(src): src.__proto__);
    if (!proto) {
        proto = src.constructor.prototype; //this line would probably only be reached by very old browsers 
    }
    var dest = object_create(proto);

    //add this object to the visited array
    _visited.push(src);
    _copiesVisited.push(dest);

    for (var key in src) {
        //Note: this does NOT preserve ES5 property attributes like 'writable', 'enumerable', etc.
        //For an example of how this could be modified to do so, see the singleMixin() function
        dest[key] = deepCopy(src[key], _visited, _copiesVisited);
    }
    return dest;
}

//If Object.create isn't already defined, we just do the simple shim,
//without the second argument, since that's all we need here
var object_create = Object.create;
if (typeof object_create !== 'function') {
    object_create = function(o) {
        function F() {}
        F.prototype = o;
        return new F();
    };
}

30

নিম্নলিখিত একই বস্তুর দুটি দৃষ্টান্ত তৈরি করে। আমি এটি খুঁজে পেয়েছি এবং বর্তমানে এটি ব্যবহার করছি। এটি সহজ এবং ব্যবহারযোগ্য।

var objToCreate = JSON.parse(JSON.stringify(cloneThis));

এই উত্তরটিতে কিছু ভুল আছে? এটি একক সমাধান হিসাবে আরও কার্যকর, তবুও সহজ; তবে jQuery সমাধান আরও জনপ্রিয়। কেন এমন?
আনুষ্ঠানিক

হ্যাঁ আমাকে জানাবেন। মনে হচ্ছে এটি উদ্দেশ্য হিসাবে কাজ করছে, যদি কোথাও কোনও গোপন ভাঙ্গা দেখা যায় তবে আমার একটি আলাদা সমাধান ব্যবহার করা দরকার।
নাথান রজার্স

4
একটি সাধারণ অবজেক্টের জন্য, ক্রোমে প্রদত্ত উত্তরের তুলনায় এটি প্রায় 6 গুণ কম ধীরে ধীরে এবং অবজেক্টটির জটিলতা বাড়ার সাথে সাথে ধীরে ধীরে ধীরে ধীরে বেড়ে যায়। এটি মারাত্মকভাবে স্কেল করে এবং খুব দ্রুত আপনার অ্যাপ্লিকেশনটিকে বাধা দিতে পারে।
টিক

1
আপনার ডেটা লাগবে না, কেবল কী চলছে তা বোঝার জন্য। এই ক্লোনিং কৌশলটি পুরো বস্তুকে একটি স্ট্রিংয়ে ক্রমিক করে, তারপরে কোনও বস্তু তৈরির জন্য স্ট্রিং সিরিয়ালাইজেশনটিকে পার্স করে। অন্তর্নিহিতভাবে এটি কেবল কিছু মেমরি পুনরায় সাজানোর চেয়ে অনেক ধীর হতে চলেছে (এটি আরও পরিশীলিত ক্লোনগুলি যা করে)। তবে যা বলা হচ্ছে, ছোট থেকে মাঝারি আকারের প্রকল্পগুলির জন্য (আপনার "মাঝারি আকারের" সংজ্ঞাটির উপর নির্ভর করে) কে এমনকি 1000x কম দক্ষ কিনা তা যত্ন করে? যদি আপনার অবজেক্টগুলি ছোট হয় এবং আপনি তাদের কোনও এক টন 1000x ক্লোন না করেন তবে কার্যত কিছুই নেই।
মেশিনঘস্ট

3
এছাড়াও, এই পদ্ধতিটি পদ্ধতিগুলি (বা JSON এ অনুমোদিত নয় এমন কোনও সামগ্রী) হারায়, এবং - JSON.stringify তারিখের অবজেক্টগুলিকে স্ট্রিংগুলিতে রূপান্তর করবে, ... এবং অন্যভাবে নয়;) এই সমাধানটি বন্ধ রাখুন।
মিঃ এমটি

22

ক্রকফোর্ড এই ফাংশনটি ব্যবহার করে পরামর্শ দেয় (এবং আমি পছন্দ করি):

function object(o) {
    function F() {}
    F.prototype = o;
    return new F();
}

var newObject = object(oldObject);

এটি ক্ষয়িষ্ণু, প্রত্যাশার মতো কাজ করে এবং আপনার লাইব্রেরি লাগবে না।


সম্পাদনা করুন:

এটি একটি পলিফিল Object.create, তাই আপনি এটিও ব্যবহার করতে পারেন।

var newObject = Object.create(oldObject);

দ্রষ্টব্য: আপনি যদি এর কিছু ব্যবহার করেন তবে কিছু পুনরাবৃত্তি যারা ব্যবহার করেন তাদের সাথে আপনার সমস্যা হতে পারে hasOwnProperty। কারণ, createউত্তরাধিকার সূত্রে নতুন খালি বস্তু তৈরি করুন oldObject। তবে এটি ক্লোনিং অবজেক্টগুলির জন্য এখনও কার্যকর এবং ব্যবহারিক।

উদাহরণস্বরূপ যদি oldObject.a = 5;

newObject.a; // is 5

কিন্তু:

oldObject.hasOwnProperty(a); // is true
newObject.hasOwnProperty(a); // is false

9
আমি ভুল হলে আমাকে সংশোধন করুন, তবে কি প্রোটোটাইপাল উত্তরাধিকারের জন্য ক্রকফোর্ডের বংশের কাজ নয়? এটি ক্লোনটির ক্ষেত্রে কীভাবে প্রযোজ্য?
অ্যালেক্স নোলাসক

3
হ্যাঁ, আমি এই আলোচনায় ভয় পেয়েছিলাম: ক্লোন, অনুলিপি এবং প্রোটোটাইপাল উত্তরাধিকারের মধ্যে ব্যবহারিক পার্থক্য কী, আপনি কখন ব্যবহার করতে হবে এবং এই পৃষ্ঠায় কোন ফাংশনগুলি আসলে কী করছে? "জাভাস্ক্রিপ্ট অনুলিপি অবজেক্ট" গুগল করে আমি এই এসও পৃষ্ঠাটি পেয়েছি। আমি যা সত্যিই সন্ধান করছিলাম তা হ'ল উপরের ফাংশনটি, তাই আমি আবার ভাগ করে নেমে এসেছি। আমার অনুমান যে প্রশ্নকারীও এটি খুঁজছিল।
ক্রিস ব্রসকি

51
ক্লোন / অনুলিপি এবং উত্তরাধিকারের মধ্যে পার্থক্যটি হ'ল - আপনার উদাহরণটি ব্যবহার করে আমি যখন ওল্ডবজেক্টের একটি সম্পত্তি পরিবর্তন করি তখন সম্পত্তিও নতুনবজেক্টে পরিবর্তিত হয়। আপনি যদি একটি অনুলিপি তৈরি করেন তবে নতুন ওবজেক্ট পরিবর্তন না করে আপনি ওল্ডবজেক্টের সাথে যা চান তা করতে পারেন।
রিডকুলি

13
এটি হ'ল ওপনপ্রপার্টি চেকটি ভেঙে দেবে যাতে কোনও বস্তুর ক্লোন করার এটি একটি দুর্দান্ত উপায় এবং আপনাকে অপ্রত্যাশিত ফলাফল দেয়।
কোরবান ব্রুক

var extendObj = function(childObj, parentObj) { var tmpObj = function () {} tmpObj.prototype = parentObj.prototype; childObj.prototype = new tmpObj(); childObj.prototype.constructor = childObj; };... ডেভিডারিফ
কোডি

22

লোড্যাশের একটি দুর্দান্ত _লোনডিপ (মান) পদ্ধতি রয়েছে:

var objects = [{ 'a': 1 }, { 'b': 2 }];

var deep = _.cloneDeep(objects);
console.log(deep[0] === objects[0]);
// => false

5
আমি এই এবং অন্যান্য সমস্ত উত্তরগুলি মুছে ফেলার পক্ষে যা একটি ইউটিলিটি লাইব্রেরির .clone(...)পদ্ধতির কেবলমাত্র এক-লাইন রেফারেন্স । প্রতিটি বড় লাইব্রেরি সেগুলি রাখবে এবং বারবার সংক্ষিপ্ত অ-বিশদ উত্তরগুলি বেশিরভাগ দর্শকের পক্ষে কার্যকর নয়, যারা এই নির্দিষ্ট লাইব্রেরিটি ব্যবহার করবেন না।
জেরেমি ব্যাংকগুলি

একটি সহজ উপায় ব্যবহার করা হয় _.merge({}, objA)। যদি কেবল লোটাস প্রথম স্থানে বস্তুগুলিকে পরিবর্তন না করে তবে cloneফাংশনটি প্রয়োজনীয় হবে না।
রিবস

7
গুগল অনুসন্ধানের জন্য জেএস বিষয়বস্তু ক্লোনিংয়ের জন্য এখানে উল্লেখ করুন। আমি লোডাশ ব্যবহার করছি তাই এই উত্তরটি আমার কাছে প্রাসঙ্গিক। দয়া করে উত্তরগুলিতে সমস্ত "উইকিপিডিয়া মুছে ফেলা" যান না।
রিবস

2
নোড 9-এ, জেএসওএন.পারস (জেএসওএন.স্ট্রিংফাই (অ্যারেঅফআউটআউট 5 কেফ্ল্যাটবজেক্টস)) _.দীপক্লোন (অ্যারেঅফআউটআউট 5 কেফ্ল্যাটবজেক্টস) এর চেয়ে অনেক বেশি দ্রুত।
ড্যান ড্যাসক্লেস্কু

21
function clone(obj)
 { var clone = {};
   clone.prototype = obj.prototype;
   for (property in obj) clone[property] = obj[property];
   return clone;
 }

17
পদ্ধতির সাথে সমস্যা, যদি আপনার কাছে বস্তুর মধ্যে সাব অবজেক্ট থাকে তবে তাদের রেফারেন্সগুলি ক্লোন করা হবে, এবং প্রতিটি উপ-অবজেক্টের মান নয়।
কামারে

1
কেবল এটিকে পুনরাবৃত্ত করুন যাতে সাব অবজেক্টগুলি গভীরভাবে ক্লোন হয়ে যায়।
ফায়াতজাফ

শুধু কৌতূহলী ... ক্লোন ভেরিয়েবলের মূল বস্তুর বৈশিষ্ট্যের জন্য পয়েন্টার থাকবে না? কারণ এটি কোনও নতুন মেমরি বরাদ্দ বলে মনে হচ্ছে
রূপেশ প্যাটেল

3
হ্যাঁ. এটি কেবল একটি অগভীর অনুলিপি, সুতরাং ক্লোনটি মূল অবজেক্টের দ্বারা চিহ্নিত একই জিনিসগুলিকে নির্দেশ করবে।
মার্ক সিডেড

এটি কোনও উত্তর নয়। আক্ষরিক অর্থে আপনি কেবল অন্য কোনও বস্তুর রেফারেন্স সহ একটি বস্তুকে স্টাফ করছেন। উত্স অবজেক্টে পরিবর্তন করা "ক্লোন" এ পরিবর্তন করবে।
শন হুইনারি 20'19

19

অগভীর অনুলিপি ওয়ান-লাইনার ( ECMAScript 5 ম সংস্করণ ):

var origin = { foo : {} };
var copy = Object.keys(origin).reduce(function(c,k){c[k]=origin[k];return c;},{});

console.log(origin, copy);
console.log(origin == copy); // false
console.log(origin.foo == copy.foo); // true

এবং অগভীর অনুলিপি ওয়ান-লাইনার ( ECMAScript 6th ষ্ঠ সংস্করণ , ২০১৫):

var origin = { foo : {} };
var copy = Object.assign({}, origin);

console.log(origin, copy);
console.log(origin == copy); // false
console.log(origin.foo == copy.foo); // true

6
এটি সাধারণ বস্তুর জন্য সূক্ষ্ম হতে পারে তবে এটি কেবল সম্পত্তি মানগুলি অনুলিপি করে। এটি প্রোটোটাইপ চেইনে স্পর্শ করে না এবং Object.keysএটি ব্যবহার করে অগণিত এবং উত্তরাধিকারসূত্রে প্রাপ্ত বৈশিষ্ট্যগুলি এড়িয়ে যায়। এছাড়াও, এটি সরাসরি অ্যাসাইনমেন্ট করে সম্পত্তি বর্ণনাকারী হারায়।
ম্যাট বিয়ারনার

আপনি যদি প্রোটোটাইপটিও অনুলিপি করেন তবে আপনি কেবল অ-গণনাযোগ্য এবং সম্পত্তি বর্ণনাকারী অনুপস্থিত থাকবেন, হ্যাঁ? বেশ ভাল. :)
সাম

পারফরম্যান্স একদিকে রেখে, কোনও বস্তুর অগভীর অনুলিপি করার পক্ষে এটি খুব সুবিধাজনক উপায়। আমি প্রায়শই এটি ব্যবহার করে আমার প্রতিক্রিয়া উপাদানগুলিতে একটি ডেস্ট্রাকচারিং অ্যাসাইনমেন্টে নকল বিশ্রামের সম্পত্তি বাছাই করতে।
mjohnsonengr

17

কেবলমাত্র আমি AngularJS উল্লেখ না করে এবং ভেবেছিলাম যে লোকেরা জানতে চাইতে পারে ...

angular.copy গভীর অনুলিপি করা অবজেক্ট এবং অ্যারেগুলির একটি পদ্ধতিও সরবরাহ করে।


অথবা এটি jQiery প্রসারিত হিসাবে একইভাবে ব্যবহৃত হতে পারে:angular.extend({},obj);
গ্যালভানি

2
@ গালভানি: এটি লক্ষ করা উচিত jQuery.extendএবং angular.extendএটি উভয়ই অগভীর অনুলিপি। angular.copyএকটি গভীর অনুলিপি।
ড্যান অ্যাটকিনসন

16

অ্যারের-মতো বস্তুর জন্য এখনও কোনও আদর্শ গভীর ক্লোন অপারেটর নেই বলে মনে হচ্ছে। নীচের কোডটি যেমন চিত্রিত করেছে, জন রেসিগের jQuery ক্লোনার অ-সংখ্যাযুক্ত বৈশিষ্ট্যযুক্ত অ্যারেগুলিকে অ্যারে নয় এমনগুলিতে পরিণত করে এবং RegDwight এর JSON ক্লোনার অ-সংখ্যাযুক্ত বৈশিষ্ট্যগুলি ফেলে দেয় drops নিম্নলিখিত পরীক্ষাগুলি একাধিক ব্রাউজারে এই পয়েন্টগুলি চিত্রিত করে:

function jQueryClone(obj) {
   return jQuery.extend(true, {}, obj)
}

function JSONClone(obj) {
   return JSON.parse(JSON.stringify(obj))
}

var arrayLikeObj = [[1, "a", "b"], [2, "b", "a"]];
arrayLikeObj.names = ["m", "n", "o"];
var JSONCopy = JSONClone(arrayLikeObj);
var jQueryCopy = jQueryClone(arrayLikeObj);

alert("Is arrayLikeObj an array instance?" + (arrayLikeObj instanceof Array) +
      "\nIs the jQueryClone an array instance? " + (jQueryCopy instanceof Array) +
      "\nWhat are the arrayLikeObj names? " + arrayLikeObj.names +
      "\nAnd what are the JSONClone names? " + JSONCopy.names)

14
যেমন অন্যরা রেজিগের উত্তরের মন্তব্যে উল্লেখ করেছেন, আপনি যদি কোনও অ্যারের মতো অবজেক্টটি ক্লোন করতে চান তবে আপনি প্রসারিত কলে {[[[] তে পরিবর্তন করতে পারেন, যেমন jQuery.extend (সত্য, [],
আপত্তি

15

আপনার উদ্দেশ্যটি "সাধারণ পুরানো জাভাস্ক্রিপ্ট অবজেক্ট" ক্লোন করা কিনা তার উপর নির্ভর করে আমার দুটি ভাল উত্তর রয়েছে।

আসুন ধরে নেওয়া যাক আপনার উদ্দেশ্যটি উত্স অবজেক্টে কোনও প্রোটোটাইপ উল্লেখ ছাড়াই একটি সম্পূর্ণ ক্লোন তৈরি করা create যদি আপনি একটি সম্পূর্ণ ক্লোনটির প্রতি আগ্রহী না হন তবে আপনি অন্যান্য কয়েকটি উত্তর (ক্রকফোর্ডের ধরণ) সরবরাহিত বেশিরভাগ অবজেক্ট.ক্লোন () রুটিন ব্যবহার করতে পারেন।

সাধারণ পুরানো জাভাস্ক্রিপ্ট অবজেক্টের জন্য, আধুনিক রানটাইমগুলিতে কোনও বস্তুর ক্লোন করার একটি চেষ্টা করা এবং সত্যিকারের ভাল উপায়টি খুব সহজ:

var clone = JSON.parse(JSON.stringify(obj));

নোট করুন যে উত্স অবজেক্টটি অবশ্যই একটি খাঁটি JSON অবজেক্ট হবে। এটি বলতে গেলে, এর সমস্ত নেস্টেড বৈশিষ্ট্য অবশ্যই স্কেলার (যেমন বুলিয়ান, স্ট্রিং, অ্যারে, অবজেক্ট ইত্যাদি) হতে হবে। RegExp বা তারিখের মতো কোনও ফাংশন বা বিশেষ অবজেক্টের ক্লোন করা হবে না।

এটা দক্ষ? হ্যাঁ হ্যাঁ আমরা সব ধরণের ক্লোনিং পদ্ধতি চেষ্টা করেছি এবং এটি সর্বোত্তমভাবে কাজ করে। আমি নিশ্চিত যে কিছু নিনজা দ্রুত পদ্ধতিতে জড়িত হতে পারে। তবে আমি সন্দেহ করি আমরা প্রান্তিক লাভের কথা বলছি।

এই পদ্ধতির বাস্তব এবং বাস্তবায়ন সহজ। এটিকে কোনও সুবিধামূলক ফাংশনে আবদ্ধ করুন এবং যদি আপনার কিছু লাভ বারবার প্রয়োজন হয় তবে পরবর্তী সময়ে যান।

এখন, অপরিচ্ছন্ন জাভাস্ক্রিপ্ট অবজেক্টের জন্য, খুব সহজ উত্তর নেই। আসলে, জাভাস্ক্রিপ্ট ফাংশন এবং অভ্যন্তরীণ অবজেক্টের গতিশীল প্রকৃতির কারণে এটি হতে পারে না। অভ্যন্তরীণ ফাংশনগুলির সাথে একটি JSON কাঠামো গভীরভাবে ক্লোনিং করার জন্য আপনাকে সেই ফাংশন এবং তাদের অভ্যন্তরীণ প্রসঙ্গটি পুনরায় তৈরি করা দরকার। এবং জাভাস্ক্রিপ্ট কেবল এটি করার একটি মানক উপায় নেই।

এটি করার সঠিক উপায়টি আবারো, এমন কোনও সুবিধা পদ্ধতির মাধ্যমে যা আপনি আপনার কোডের মধ্যে ঘোষণা করেন এবং পুনরায় ব্যবহার করেন। সুবিধাদির পদ্ধতিটি আপনার নিজস্ব বস্তুগুলির কিছু বোঝার সাথে সমৃদ্ধ করা যেতে পারে যাতে আপনি সঠিকভাবে নতুন বস্তুর মধ্যে গ্রাফটি পুনরায় তৈরি করতে নিশ্চিত করতে পারেন।

আমরা আমাদের নিজের লেখা, কিন্তু আমি দেখেছি সেরা সাধারণ পদ্ধতি এখানে আবৃত:

http://davidwalsh.name/javascript-clone

এটি সঠিক ধারণা। লেখক (ডেভিড ওয়ালশ) সাধারণ ক্রিয়াকলাপগুলির ক্লোনিং সম্পর্কে মন্তব্য করেছেন। আপনার ব্যবহারের ক্ষেত্রে নির্ভর করে এটি আপনি বেছে নিতে বেছে নিতে পারেন।

মূল ধারণাটি হ'ল আপনাকে প্রতি-টাইপের ভিত্তিতে আপনার ফাংশনগুলির (বা প্রোটোটাইপাল ক্লাসগুলি, তাই কথা বলতে) ইনস্ট্যান্টেশন বিশেষভাবে পরিচালনা করতে হবে। এখানে, তিনি RegExp এবং তারিখের জন্য কয়েকটি উদাহরণ সরবরাহ করেছেন।

এই কোডটি সংক্ষিপ্তই নয়, এটি খুব পাঠযোগ্য। এটি প্রসারিত করা বেশ সহজ।

এটা কি দক্ষ? হ্যাঁ হ্যাঁ প্রদত্ত লক্ষ্যটি সত্যিকারের গভীর-অনুলিপি ক্লোন তৈরি করা, তারপরে আপনাকে উত্স অবজেক্ট গ্রাফের সদস্যদের হাঁটতে হবে। এই পদ্ধতির সাথে, আপনি ঠিক কীভাবে শিশু সদস্যদের চিকিত্সা করবেন এবং কীভাবে কাস্টম প্রকারগুলি ম্যানুয়ালি হ্যান্ডেল করবেন twe

সুতরাং আপনি সেখানে যান। দুটি পন্থা। উভয়ই আমার দৃষ্টিতে দক্ষ।


13

এটি সাধারণত সবচেয়ে কার্যকর সমাধান নয়, তবে এটি আমার যা প্রয়োজন তা করে। নীচে সাধারণ পরীক্ষার কেস ...

function clone(obj, clones) {
    // Makes a deep copy of 'obj'. Handles cyclic structures by
    // tracking cloned obj's in the 'clones' parameter. Functions 
    // are included, but not cloned. Functions members are cloned.
    var new_obj,
        already_cloned,
        t = typeof obj,
        i = 0,
        l,
        pair; 

    clones = clones || [];

    if (obj === null) {
        return obj;
    }

    if (t === "object" || t === "function") {

        // check to see if we've already cloned obj
        for (i = 0, l = clones.length; i < l; i++) {
            pair = clones[i];
            if (pair[0] === obj) {
                already_cloned = pair[1];
                break;
            }
        }

        if (already_cloned) {
            return already_cloned; 
        } else {
            if (t === "object") { // create new object
                new_obj = new obj.constructor();
            } else { // Just use functions as is
                new_obj = obj;
            }

            clones.push([obj, new_obj]); // keep track of objects we've cloned

            for (key in obj) { // clone object members
                if (obj.hasOwnProperty(key)) {
                    new_obj[key] = clone(obj[key], clones);
                }
            }
        }
    }
    return new_obj || obj;
}

চক্রীয় অ্যারে পরীক্ষা ...

a = []
a.push("b", "c", a)
aa = clone(a)
aa === a //=> false
aa[2] === a //=> false
aa[2] === a[2] //=> false
aa[2] === aa //=> true

ফাংশন পরীক্ষা...

f = new Function
f.a = a
ff = clone(f)
ff === f //=> true
ff.a === a //=> false

11

AngularJS

আচ্ছা আপনি যদি কৌণিক ব্যবহার করছেন তবে আপনি এটিও করতে পারেন

var newObject = angular.copy(oldObject);

11

আমি এখানে সর্বাধিক ভোট দিয়ে উত্তর সাথে একমত নই । একজন Recursive ডীপ ক্লোন হয় অনেক দ্রুত চেয়ে JSON.parse (JSON.stringify (obj)) পদ্ধতির উল্লেখ করেছে।

  • জাসস্পিফ এটি এখানে এক নম্বরে স্থান নিয়েছে: https://jsperf.com/deep-copy-vs-json-stringify-json-parse/5
  • উপরের উত্তর থেকে জেএসবেন আপডেট হয়েছে তা দেখানোর জন্য আপডেট করা হয়েছে যে পুনরাবৃত্তাকারী গভীর ক্লোনটি উল্লিখিত অন্য সকলকে মারধর করে: http://jsben.ch/13YKQ

এবং এখানে দ্রুত রেফারেন্স জন্য ফাংশন:

function cloneDeep (o) {
  let newO
  let i

  if (typeof o !== 'object') return o

  if (!o) return o

  if (Object.prototype.toString.apply(o) === '[object Array]') {
    newO = []
    for (i = 0; i < o.length; i += 1) {
      newO[i] = cloneDeep(o[i])
    }
    return newO
  }

  newO = {}
  for (i in o) {
    if (o.hasOwnProperty(i)) {
      newO[i] = cloneDeep(o[i])
    }
  }
  return newO
}

2
আমি এই পদ্ধতির পছন্দ করি কিন্তু এটি তারিখগুলি সঠিকভাবে পরিচালনা করে না; if(o instanceof Date) return new Date(o.valueOf());নাল for
লুইস

বিজ্ঞপ্তি সংক্রান্ত রেফারেন্সগুলিতে ক্রাশ।
হ্যারি

সর্বশেষ স্থিতিশীল ফায়ারফক্সে, এটি জেসবেন.চ লিঙ্কের অন্যান্য কৌশলগুলির চেয়ে অনেক বেশি দীর্ঘতর আকারের বা আরও বেশি ক্রমের দ্বারা। এটি অন্যকে ভুল পথে মারধর করে।
ডাব্লুবিটি

11
// obj target object, vals source object
var setVals = function (obj, vals) {
    if (obj && vals) {
        for (var x in vals) {
            if (vals.hasOwnProperty(x)) {
                if (obj[x] && typeof vals[x] === 'object') {
                    obj[x] = setVals(obj[x], vals[x]);
                } else {
                    obj[x] = vals[x];
                }
            }
        }
    }
    return obj;
};

10

কেবলমাত্র যখন আপনি ECMAScript 6 বা ট্রান্সপোর্টার ব্যবহার করতে পারেন ।

বৈশিষ্ট্য:

  • অনুলিপি করার সময় গিটার / সেটার ট্রিগার করবেন না।
  • গেটর / সেটার সংরক্ষণ করে।
  • প্রোটোটাইপ তথ্য সংরক্ষণ করে।
  • উভয় বস্তু-আক্ষরিক এবং কার্যকরী OO রচনা শৈলীর সাথে কাজ করে।

কোড:

function clone(target, source){

    for(let key in source){

        // Use getOwnPropertyDescriptor instead of source[key] to prevent from trigering setter/getter.
        let descriptor = Object.getOwnPropertyDescriptor(source, key);
        if(descriptor.value instanceof String){
            target[key] = new String(descriptor.value);
        }
        else if(descriptor.value instanceof Array){
            target[key] = clone([], descriptor.value);
        }
        else if(descriptor.value instanceof Object){
            let prototype = Reflect.getPrototypeOf(descriptor.value);
            let cloneObject = clone({}, descriptor.value);
            Reflect.setPrototypeOf(cloneObject, prototype);
            target[key] = cloneObject;
        }
        else {
            Object.defineProperty(target, key, descriptor);
        }
    }
    let prototype = Reflect.getPrototypeOf(source);
    Reflect.setPrototypeOf(target, prototype);
    return target;
}

9

এখানে একটি বিস্তৃত ক্লোন () পদ্ধতি যা কোনও জাভাস্ক্রিপ্ট অবজেক্টকে ক্লোন করতে পারে। এটি প্রায় সমস্ত ক্ষেত্রে পরিচালনা করে:

function clone(src, deep) {

    var toString = Object.prototype.toString;
    if (!src && typeof src != "object") {
        // Any non-object (Boolean, String, Number), null, undefined, NaN
        return src;
    }

    // Honor native/custom clone methods
    if (src.clone && toString.call(src.clone) == "[object Function]") {
        return src.clone(deep);
    }

    // DOM elements
    if (src.nodeType && toString.call(src.cloneNode) == "[object Function]") {
        return src.cloneNode(deep);
    }

    // Date
    if (toString.call(src) == "[object Date]") {
        return new Date(src.getTime());
    }

    // RegExp
    if (toString.call(src) == "[object RegExp]") {
        return new RegExp(src);
    }

    // Function
    if (toString.call(src) == "[object Function]") {

        //Wrap in another method to make sure == is not true;
        //Note: Huge performance issue due to closures, comment this :)
        return (function(){
            src.apply(this, arguments);
        });
    }

    var ret, index;
    //Array
    if (toString.call(src) == "[object Array]") {
        //[].slice(0) would soft clone
        ret = src.slice();
        if (deep) {
            index = ret.length;
            while (index--) {
                ret[index] = clone(ret[index], true);
            }
        }
    }
    //Object
    else {
        ret = src.constructor ? new src.constructor() : {};
        for (var prop in src) {
            ret[prop] = deep
                ? clone(src[prop], true)
                : src[prop];
        }
    }
    return ret;
};

এটি আদিমদেরকে মোড়কের বস্তুতে রূপান্তরিত করে, বেশিরভাগ ক্ষেত্রেই এটি ভাল সমাধান নয়।
ডানুবিয়ান নাবিক

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