जावास्क्रिप्ट में किसी ऑब्जेक्ट को गहरी क्लोन करने का सबसे कुशल तरीका क्या है?


5180

जावास्क्रिप्ट ऑब्जेक्ट क्लोन करने का सबसे कुशल तरीका क्या है? मैंने देखा obj = eval(uneval(o));जा रहा है, लेकिन यह गैर-मानक है और केवल फ़ायरफ़ॉक्स द्वारा समर्थित है

मैंने चीजें की हैं, obj = JSON.parse(JSON.stringify(o));लेकिन दक्षता पर सवाल उठाएं।

मैंने विभिन्न दोषों के साथ पुनरावर्ती नकल कार्यों को भी देखा है।
मुझे आश्चर्य है कि कोई विहित समाधान मौजूद नहीं है।


566
बुराई बुराई नहीं है। खराब का उपयोग करना है। यदि आप इसके दुष्प्रभावों से डरते हैं तो आप इसका गलत उपयोग कर रहे हैं। आपके द्वारा डरने वाले दुष्प्रभाव इसका उपयोग करने के कारण हैं। क्या वास्तव में किसी ने भी आपके प्रश्न का उत्तर दिया?
जेम्स

15
क्लोनिंग ऑब्जेक्ट एक मुश्किल व्यवसाय है, विशेष रूप से मनमाना संग्रह की कस्टम वस्तुओं के साथ। जो शायद ऐसा करने के लिए कोई आउट-ऑफ-द-बॉक्स तरीका नहीं है।
b01

12
eval()आम तौर पर एक बुरा विचार है क्योंकि कई जावास्क्रिप्ट इंजन के ऑप्टिमाइज़र को उन चर से निपटना पड़ता है जो कि चर के माध्यम से सेट होते हैंeval । बस eval()आपके कोड में होने से खराब प्रदर्शन हो सकता है।
user56reinstatemonica8


12
ध्यान दें कि JSONविधि किसी भी जावास्क्रिप्ट प्रकार को ढीला कर देगी जिसमें JSON का कोई समकक्ष नहीं है। उदाहरण के लिए: 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}
ओरियडैम

जवाबों:


4729

देशी गहरी क्लोनिंग

इसे "संरचित क्लोनिंग" कहा जाता है, यह नोड 11 और बाद में प्रयोगात्मक रूप से काम करता है, और उम्मीद है कि ब्राउज़रों में उतरेगा। देखें इस उत्तर अधिक जानकारी के लिए।

डेटा हानि के साथ फास्ट क्लोनिंग - JSON.parse / stringify

आप उपयोग नहीं करते हैं Dateरों, कार्य, undefined, Infinity, regexps, मैप्स, सेट, Blobs, FileLists, ImageDatas, विरल सरणी, Typed Arrays या अपने वस्तु के भीतर अन्य जटिल प्रकार, गहरी क्लोन करने के लिए एक बहुत ही सरल एक लाइनर एक वस्तु है:

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

बेंचमार्क के लिए कॉर्बन का जवाब देखें ।

लाइब्रेरी का उपयोग करके विश्वसनीय क्लोनिंग

चूंकि क्लोनिंग ऑब्जेक्ट्स तुच्छ नहीं हैं (जटिल प्रकार, परिपत्र संदर्भ, फ़ंक्शन आदि), अधिकांश प्रमुख लाइब्रेरी क्लोन ऑब्जेक्ट्स को फ़ंक्शन प्रदान करते हैं। पहिया को सुदृढ़ न करें - यदि आप पहले से ही एक पुस्तकालय का उपयोग कर रहे हैं, तो जांचें कि क्या उसमें ऑब्जेक्ट क्लोनिंग फ़ंक्शन है। उदाहरण के लिए,

  • दर्ज करना - cloneDeep; के माध्यम से अलग से आयात किया जा सकता lodash.clonedeep मॉड्यूल और यदि आप पहले से ही एक पुस्तकालय एक गहरी क्लोनिंग समारोह में प्रावधान है कि उपयोग नहीं कर रहे शायद तुम्हारा सबसे अच्छा विकल्प है
  • AngularJS - 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
@ThiefMaster github.com/jquery/jquery/blob/master/src/core.js 276 लाइन पर (इसमें थोड़ा सा कोड है जो कुछ और करता है लेकिन "JS में यह कैसे करें" के लिए कोड है :)
Rune FS

7
यहाँ jQuery गहरी प्रतिलिपि के पीछे जेएस कोड है, किसी के लिए भी रुचि: github.com/jquery/jquery/blob/master/src/core.js#L265-327
एलेक्स डब्ल्यू

194
ओह! बस सुपर-स्पष्ट होने के लिए: कोई भी विचार क्यों इस प्रतिक्रिया को सही उत्तर के रूप में चुना गया था, यह नीचे दिए गए प्रतिक्रियाओं का जवाब था: stackoverflow.com/a/122190/6524 (जो सिफारिश कर रहा था .clone(), जो होने के लिए सही कोड नहीं है इस संदर्भ में उपयोग करना)। दुर्भाग्य से यह प्रश्न इतने सारे संशोधनों के माध्यम से चला गया है मूल चर्चा अब और भी स्पष्ट नहीं है! कृपया केवल कोर्बन की सलाह का पालन करें और एक लूप लिखें या गुणों को सीधे एक नई वस्तु पर कॉपी करें, यदि आप गति के बारे में परवाह करते हैं। या इसे अपने लिए परखें!
जॉन रेसिग

9
यह एक जावास्क्रिप्ट प्रश्न (jQuery का कोई उल्लेख नहीं है)।
Gphilip

60
JQuery का उपयोग किए बिना कोई ऐसा कैसे करेगा?
Awesomeness01

2264

इस बेंचमार्क को चेकआउट करें: http://jsben.ch/#/bWfk9

मेरे पिछले परीक्षणों में जहां गति एक मुख्य चिंता का विषय था

JSON.parse(JSON.stringify(obj))

किसी ऑब्जेक्ट को डीप क्लोन करने का सबसे धीमा तरीका है (यह 10-20% तक फ्लैग सेट के साथ jQuery.extend की तुलना में धीमा है deep)।

jQuery.extend बहुत तेज है जब deepझंडा false(उथले क्लोन) पर सेट किया जाता है । यह एक अच्छा विकल्प है, क्योंकि इसमें प्रकार सत्यापन के लिए कुछ अतिरिक्त तर्क शामिल हैं और अपरिभाषित गुणों की नकल नहीं करते हैं, लेकिन यह आपको थोड़ा धीमा भी करेगा।

यदि आप उन वस्तुओं की संरचना को जानते हैं जिन्हें आप क्लोन करने की कोशिश कर रहे हैं या गहरी नेस्टेड सरणियों से बच सकते हैं तो आप for (var i in obj)hasOwnProperty की जाँच करते समय अपनी वस्तु को क्लोन करने के लिए एक सरल लूप लिख सकते हैं और यह jQuery की तुलना में बहुत तेज़ होगा।

अंत में अगर आप एक ज्ञात ऑब्जेक्ट संरचना को एक हॉट लूप में क्लोन करने का प्रयास कर रहे हैं, तो आप क्लोन प्रक्रिया को सरल रूप से करके और फिर से ऑब्जेक्ट का निर्माण करके MUCH MUCH MORE PERFORMANCE प्राप्त कर सकते हैं।

जावास्क्रिप्ट ट्रेस इंजन for..inलूप को अनुकूलित करने के लिए चूसते हैं और hasOwnProperty को चेक करते हुए आपको धीमा कर देंगे। मैन्युअल क्लोन जब गति एक निरपेक्ष होना चाहिए।

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

ऑब्जेक्ट JSON.parse(JSON.stringify(obj))पर विधि का उपयोग करने से सावधान रहें Date- JSON.stringify(new Date())आईएसओ प्रारूप में तारीख का एक स्ट्रिंग प्रतिनिधित्व लौटाता है, जो किसी ऑब्जेक्ट में वापस JSON.parse() नहींDate बदलता है। अधिक विवरण के लिए यह उत्तर देखें

इसके अतिरिक्त, कृपया ध्यान दें कि, क्रोम 65 में, कम से कम, देशी क्लोनिंग जाने का रास्ता नहीं है। JSPerf के अनुसार, एक नया फ़ंक्शन बनाकर देशी क्लोनिंग का प्रदर्शन JSON.stringify की तुलना में लगभग 800x धीमा है, जो कि बोर्ड भर में अविश्वसनीय रूप से तेज़ है।

ES6 के लिए अपडेट करें

यदि आप जावास्क्रिप्ट ES6 का उपयोग कर रहे हैं तो क्लोनिंग या उथले प्रतिलिपि के लिए इस मूल विधि का प्रयास करें।

Object.assign({}, obj);

4
@trysis Object.create ऑब्जेक्ट को क्लोन नहीं कर रहा है, प्रोटोटाइप ऑब्जेक्ट का उपयोग कर रहा है ... jsfiddle.net/rahpuser/yufzc1jt/2
rahpuser

105
यह विधि keysआपके उन लोगों को भी हटा देगी object, जिनके पास functionsउनके मूल्य हैं, क्योंकि यह JSONफ़ंक्शन का समर्थन नहीं करता है।
कारलेन किशमिरन

39
यह भी ध्यान रखें कि JSON.parse(JSON.stringify(obj))दिनांक ऑब्जेक्ट्स का उपयोग करने से ISO8601 प्रारूप में स्ट्रिंग प्रतिनिधित्व में दिनांक को UTC में भी परिवर्तित किया जाएगा ।
dnlgmzddr

31
JSON दृष्टिकोण भी परिपत्र संदर्भ पर चुटकुले।
अमीर फिर से

28
@ उलट, Object.assign ({}, objToClone) ऐसा लगता है जैसे यह एक उथला क्लोन है - हालांकि इसका इस्तेमाल देव उपकरण कंसोल में खेलते समय किया जाता है, ऑब्जेक्ट क्लोन अभी भी क्लोन ऑब्जेक्ट के संदर्भ में इंगित किया गया है। इसलिए मुझे नहीं लगता कि यह वास्तव में यहां लागू है।
गैरेट सिम्पसन

473

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

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

86
इस दृष्टिकोण के चुनाव के रूप में मैंने अभी पाया है कि यदि आपकी वस्तु में कोई कार्य है (मेरा आंतरिक गेटर्स और सेटर है) तो ये तब खो जाते हैं जब कड़े हो जाते हैं .. यदि आप सभी को इस विधि की आवश्यकता है तो ठीक है ..
Markive

31
@ जैसन, इस विधि की वजह से उथली नकल की तुलना में धीमी है (गहरी वस्तु पर) यह विधि, परिभाषा के अनुसार, गहरी प्रतियां है। लेकिन चूंकि JSONमूल कोड (अधिकांश ब्राउज़रों में) लागू किया गया है, यह किसी भी अन्य जावास्क्रिप्ट-आधारित गहरी प्रतिलिपि समाधान का उपयोग करने की तुलना में काफी तेज होगा, और कभी-कभी एक जावास्क्रिप्ट-आधारित उथले नकल तकनीक की तुलना में तेज हो सकता है (देखें: jperperf.com/cloning -आन-वस्तु / । ९)।
MiJyn

35
JSON.stringify({key: undefined}) //=> "{}"
वेब_डिजाइनर

32
यह तकनीक उन सभी Dateवस्तुओं को भी नष्ट करने वाली है जो ऑब्जेक्ट के अंदर जमा होती हैं, उन्हें स्ट्रिंग रूप में परिवर्तित करती हैं।
fstab

13
यह कुछ भी है कि JSON कल्पना (का हिस्सा नहीं है कॉपी करने के लिए असफल हो जायेगी json.org )
cdmckay

397

संरचित क्लोनिंग

HTML मानक में एक आंतरिक संरचित क्लोनिंग / क्रमांकन एल्गोरिथ्म शामिल है जो वस्तुओं के गहरे क्लोन बना सकता है। यह अभी भी कुछ अंतर्निहित प्रकारों तक सीमित है, लेकिन JSON द्वारा समर्थित कुछ प्रकारों के अलावा यह Dates, RegExps, Maps, Sets, Blobs, FileLists, ImageDatas, Sparse Arrays, Typr Arrays और शायद भविष्य में और अधिक का समर्थन करता है। । यह क्लोन डेटा के भीतर संदर्भों को भी संरक्षित करता है, जिससे यह चक्रीय और पुनरावर्ती संरचनाओं का समर्थन करने की अनुमति देता है जो JSON के लिए त्रुटियां पैदा करेगा।

Node.js में समर्थन: प्रायोगिक j

v8Node.js वर्तमान में मॉड्यूल (नोड 11) के रूप में सीधे संरचित क्रमबद्धता एपीआई को उजागर करता है , लेकिन इस कार्यक्षमता अभी भी "प्रायोगिक", और भविष्य के संस्करणों में परिवर्तन या हटाने के अधीन के रूप में चिह्नित किया गया है। यदि आप एक संगत संस्करण का उपयोग कर रहे हैं, तो किसी ऑब्जेक्ट को क्लोन करना उतना ही सरल है:

const v8 = require('v8');

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

ब्राउज़रों में प्रत्यक्ष समर्थन: शायद आखिरकार? 😐

ब्राउज़र्स वर्तमान में संरचित क्लोनिंग एल्गोरिथ्म के लिए एक सीधा इंटरफ़ेस प्रदान नहीं करते हैं, लेकिन एक वैश्विक structuredClone()फ़ंक्शन पर चर्चा की गई है GitHub पर whatwg / html # 793 । जैसा कि वर्तमान में प्रस्तावित है, अधिकांश प्रयोजनों के लिए इसका उपयोग करना उतना ही सरल होगा:

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

तुल्यकालिक Workarounds: भयानक! 🤢

तुल्यकालिक रूप से संरचित क्लोन बनाने के लिए कोई अच्छा विकल्प नहीं हैं। यहाँ कुछ अव्यवहारिक हैक्स के बजाय हैं।

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;
};

उदाहरण का उपयोग करें:

हालांकि तुल्यकालिक, यह बेहद धीमा हो सकता है। यह ब्राउज़र इतिहास में हेरफेर करने से जुड़े सभी ओवरहेड को उकसाता है। इस विधि को बार-बार कॉल करने पर Chrome अस्थायी रूप से अनुत्तरदायी बन सकता है।

Notificationनिर्माता अपने संबद्ध डेटा का संरचित क्लोन पैदा करता है। यह उपयोगकर्ता को एक ब्राउज़र सूचना प्रदर्शित करने का भी प्रयास करता है, लेकिन यह तब तक चुपचाप विफल रहेगा जब तक आपने अधिसूचना अनुमति का अनुरोध नहीं किया है। यदि आपके पास अन्य प्रयोजनों के लिए अनुमति है, तो हम तुरंत हमारे द्वारा बनाई गई अधिसूचना को बंद कर देंगे।

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

उदाहरण का उपयोग करें:


3
@rynah मैं सिर्फ फिर से कल्पना के माध्यम से देखा और आप सही हैं: history.pushState()और history.replaceState()दोनों तरीके तुल्यकालिक रूप history.stateसे अपने पहले तर्क के एक संरचित क्लोन के लिए सेट । थोड़ा अजीब है, लेकिन यह काम करता है। मैं अब अपना जवाब अपडेट कर रहा हूं।
जेरेमी बैंक्स

40
यह सिर्फ इतना गलत है! यह एपीआई इस तरह से इस्तेमाल करने के लिए नहीं है।
फरदीन के।

209
जैसा कि उस व्यक्ति ने फ़ायरफ़ॉक्स में पुशस्टेट लागू किया था, मुझे इस हैक पर गर्व और विद्रोह का एक अजीब मिश्रण महसूस होता है। अच्छी तरह से किया दोस्तों।
जस्टिन एल।

pushState या Notification Hack कुछ ऑब्जेक्ट प्रकारों जैसे फंक्शन के लिए काम नहीं करता है
शिशिर अरोड़ा

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
JQuery समाधान DOM तत्वों के लिए काम करेगा, लेकिन किसी भी वस्तु के लिए नहीं। मूटूलों की एक ही सीमा है। काश उनके पास किसी भी वस्तु के लिए एक सामान्य "क्लोन" होता ... पुनरावर्ती समाधान कुछ भी काम करना चाहिए। यह शायद जाने का रास्ता है।
jschrab

5
यह फ़ंक्शन टूट जाता है यदि ऑब्जेक्ट क्लोन किया जा रहा है, जिसमें एक कंस्ट्रक्टर है जिसे मापदंडों की आवश्यकता होती है। ऐसा लगता है कि हम इसे "var temp = new Object ()" में बदल सकते हैं और क्या यह हर मामले में काम करता है, नहीं?
एंड्रयू अर्कोट

3
एंड्रयू, यदि आप इसे var अस्थायी = नई वस्तु () में बदलते हैं, तो आपके क्लोन का मूल ऑब्जेक्ट के समान प्रोटोटाइप नहीं होगा। प्रयोग करके देखें: 'var newProto = function () {}; newProto.prototype = obj.constructor; var अस्थायी = नया newProto (); '
15

1
लाइमकोडर के उत्तर के समान, नीचे दिए गए मेरे उत्तर को देखें कि यह बिना कंस्ट्रक्टर को कॉल करने के लिए कैसे करें: stackoverflow.com/a/13333781/560114
मैट ब्राउन

3
उन वस्तुओं के लिए जिनमें उप-भाग (यानी, वस्तुओं के नेटवर्क) के संदर्भ हैं, यह काम नहीं करता है: यदि दो संदर्भ एक ही उप-ऑब्जेक्ट को इंगित करते हैं, तो प्रतिलिपि में इसकी दो अलग-अलग प्रतियां होती हैं। और अगर पुनरावर्ती संदर्भ हैं, तो फ़ंक्शन कभी भी समाप्त नहीं होगा (ठीक है, कम से कम जिस तरह से आप इसे चाहते हैं वैसे नहीं :-) इन सामान्य मामलों के लिए, आपको पहले से कॉपी की गई वस्तुओं का एक शब्दकोश जोड़ना होगा, और जांचना होगा कि क्या आपने पहले ही इसे कॉपी कर लिया है ... प्रोग्रामिंग सरल है जब आप एक सरल भाषा का उपयोग करते हैं
virtualnobi

153

कोड की एक पंक्ति में एक ऑब्जेक्ट को क्लोन करने के लिए कुशल तरीका (गहरा-क्लोन नहीं)

एक Object.assignविधि ECMAScript 2015 (ES6) मानक का हिस्सा है और ठीक वही है जो आपको चाहिए।

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

Object.assign () विधि का उपयोग एक या एक से अधिक स्रोत ऑब्जेक्ट से लक्ष्य सामग्री के सभी गणना करने योग्य गुणों के मूल्यों को कॉपी करने के लिए किया जाता है।

अधिक पढ़ें...

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
यह पुनरावर्ती रूप से कॉपी नहीं करता है इसलिए वास्तव में किसी वस्तु की क्लोनिंग की समस्या का समाधान नहीं है।
mwhite

5
इस विधि ने काम किया, हालांकि मैंने कुछ का परीक्षण किया और _.extend ({}, (obj)) BY FAR सबसे तेज था: JSON.parse की तुलना में 20x तेज और Object.assign की तुलना में 60% तेज, उदाहरण के लिए। यह सभी उप-वस्तुओं को काफी अच्छी तरह से कॉपी करता है।
निको

11
@ सफेद और गहरे क्लोन के बीच अंतर होता है। यह जवाब वास्तव में क्लोन करता है, लेकिन यह गहरी-क्लोन नहीं है।
मीरियन ह्यूजेस

57
सेशन ने गहरे क्लोन के लिए कहा। यह गहरा क्लोन नहीं करता है।
user566245

9
यह विधि एक SHOWOW कॉपी बनाती है , न कि DEEP कॉपी ! इस वजह से यह पूरी तरह से गलत जवाब है !
भरत

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
neaumusic

5
मैं इस फंक्शन को नहीं समझता। मान लीजिए from.constructorहै Dateउदाहरण के लिए। ifजब दूसरा ifपरीक्षण सफल होगा और फ़ंक्शन को वापस लौटने का कारण होगा (तब से Date != Object && Date != Array) तीसरा परीक्षण कैसे होगा ?
एडम मैककी

1
@AdamMcKee क्योंकि जावास्क्रिप्ट तर्क पारित और चर असाइनमेंट मुश्किल है । यह दृष्टिकोण बहुत अच्छा काम करता है, जिसमें तारीखें भी शामिल हैं (जो वास्तव में दूसरे परीक्षण द्वारा नियंत्रित की जाती हैं) - यहाँ परीक्षण करने के लिए फ़िडल : jsfiddle.net/zqv9q9c6
ब्रिचिंस

1
@NickSweeting: कोशिश करें - यह काम कर सकता है। यदि नहीं - इसे ठीक करें और उत्तर को अपडेट करें। यह समुदाय में यहाँ कैसे काम करता है :)
Kamarey

1
यह फ़ंक्शन परीक्षण में रेगेक्स को क्लोन नहीं करता है, स्थिति "from.constructor! = Object && from .constructor! = Array" हमेशा अन्य कंस्ट्रक्टर्स जैसे नंबर, दिनांक, और इसी तरह सही रहता है।
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 एक सादे वस्तु है।
22

यह सरणियों को भी गड़बड़ करता है, जो संख्यात्मक कुंजियों के साथ वस्तुओं में परिवर्तित हो जाते हैं।
ब्लेड

यदि आप अशक्त का उपयोग नहीं करते हैं तो कोई समस्या नहीं है।
जॉर्ज बुकरन

78

प्रदर्शन द्वारा गहरी प्रतिलिपि: सर्वश्रेष्ठ से सबसे खराब रैंक की गई

  • पुन: असाइनमेंट "=" (स्ट्रिंग सरणियाँ, संख्या सरणियाँ - केवल)
  • स्लाइस (स्ट्रिंग सरणियाँ, संख्या सरणियाँ - केवल)
  • संबंध (स्ट्रिंग सरणियाँ, संख्या सरणियाँ - केवल)
  • कस्टम फ़ंक्शन: लूप या पुनरावर्ती प्रतिलिपि के लिए
  • jQuery के $ .extend
  • JSON.parse (स्ट्रिंग सरणियाँ, संख्या सरणियाँ, ऑब्जेक्ट सरणियाँ - केवल)
  • Underscore.js की _.clone (स्ट्रिंग सरणियाँ, संख्या सरणियाँ - केवल)
  • लो-डैश की _.cloneDeep

स्ट्रिंग्स या संख्याओं की एक सरणी को कॉपी करें (एक स्तर - कोई संदर्भ बिंदु नहीं):

जब किसी सरणी में संख्याएँ और तार होते हैं - कार्य .slice (), .concat (), .splice (), असाइनमेंट ऑपरेटर "=", और Underscore.js का क्लोन फ़ंक्शन; सरणी के तत्वों की एक गहरी प्रतिलिपि बनाएगा।

जहाँ पुनर्मूल्यांकन में सबसे तेज़ प्रदर्शन होता है:

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

और .slice () के पास .concat (), http://jsperf.com/duplicate-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'}];

एक कस्टम फ़ंक्शन लिखें ($ .extend () या 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 के $ .extend का बेहतर प्रदर्शन है:


मैंने कुछ का परीक्षण किया और _.extend ({}, (obj)) सबसे तेज था: JSON.parse की तुलना में 20x तेज और Object.assign की तुलना में 60% तेज, उदाहरण के लिए। यह सभी उप-वस्तुओं को काफी अच्छी तरह से कॉपी करता है।
निको

4
आपके सभी उदाहरण उथले हैं, एक स्तर। यह एक अच्छा जवाब नहीं है। प्रश्न गहरी क्लोनिंग यानी कम से कम दो स्तरों के बारे में था ।
कार्ल मॉरिसन

1
एक गहरी प्रतिलिपि तब होती है जब कोई वस्तु अन्य वस्तुओं के संदर्भ बिंदुओं के उपयोग के बिना अपने संपूर्ण रूप में कॉपी की जाती है। "डीप ए सरणी ऑफ़ द ऑब्जेक्ट्स", जैसे कि jQuery.extend () और कस्टम फंक्शन (जो पुनरावर्ती है) की वस्तुओं को "कम से कम दो स्तरों" के साथ कॉपी करें। तो, नहीं सभी उदाहरण "एक स्तर" प्रतियां हैं।
tfmontague

1
मुझे आपकी कस्टम कॉपी फ़ंक्शन पसंद है, लेकिन आपको अशक्त मूल्यों को बाहर करना चाहिए, अन्यथा सभी शून्य मान वस्तुओं में परिवर्तित हो रहे हैं, अर्थात:out[key] = (typeof v === "object" && v !== null) ? copy(v) : v;
josi

2
@HossamMourad - बग को जोशी द्वारा फ़रवरी 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 } } 

3. लो-डैश के _.cloneDeep लिंक लॉश का उपयोग करना

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 } } 

4. Object.assign () पद्धति का उपयोग करना

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. 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.)

JSBEN.CH प्रदर्शन बेंचमार्किंग खेल का मैदान 1 ~ 3 http://jsben.ch/KVQLd प्रदर्शन दीप जावास्क्रिप्ट में वस्तुओं की नकल


5
Object.assign()एक गहरी प्रतिलिपि प्रदर्शन नहीं करता है
रॉयमुनसन

1
आपको इनके लिए बेंचमार्क जोड़ना चाहिए; यह बहुत मददगार होगा
जेसीओलम

जब मैं उस ऑब्जेक्ट पर "बनाई गई विधि" का उपयोग करता हूं जिसमें एक सरणी होती है तो मैं उस पर पॉप () या ब्याह () का उपयोग करने में असमर्थ था, मुझे समझ नहीं आता कि क्यों? 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 को संशोधित नहीं कर सकता)
hugogogo

अरे, आपका आखिरी उदाहरण गलत है। मेरी राय में, आपको गलत उदाहरण के लिए _clone का उपयोग करना चाहिए न कि _cloneDeep का।
kenanyildiz

यह बनाया गया तरीका (2.) सरणियों के लिए काम नहीं करेगा, क्या यह होगा?
इनवो सेवेन

57

वहाँ एक पुस्तकालय ("क्लोन" कहा जाता है) , यह काफी अच्छी तरह से करता है। यह मनमानी वस्तुओं की सबसे पूर्ण पुनरावर्ती क्लोनिंग / प्रतिलिपि प्रदान करता है जो मुझे पता है। यह परिपत्र संदर्भों का भी समर्थन करता है, जो अन्य उत्तरों द्वारा कवर नहीं किया गया है, फिर भी।

आप इसे npm पर भी पा सकते हैं । यह ब्राउज़र के साथ-साथ Node.js. के लिए भी उपयोग किया जा सकता है

इसका उपयोग करने के तरीके के बारे में एक उदाहरण इस प्रकार है:

इसके साथ स्थापित करें

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
मनमाने ढंग से नेस्टेड वस्तुओं को क्लोन करने के लिए npm क्लोन मेरे लिए अमूल्य है। यह सही जवाब है।
एंडी रे

चलो कहने की तुलना में आपके परिवाद का प्रदर्शन क्या है JSON.parse(JSON.stringify(obj))?
16

यहां एक पुस्तकालय है जो बताता है कि तेज विकल्प हैं। हालांकि परीक्षण नहीं किया गया।
21

अच्छा समाधान और यह परिपत्र संदर्भ (JSON के पार के विपरीत) का समर्थन करता है
ल्यूक

55

Cloning जेएस में एक ऑब्जेक्ट हमेशा एक चिंता का विषय था, लेकिन ईएस 6 से पहले यह सब था, मैं नीचे दिए गए जावास्क्रिप्ट में किसी ऑब्जेक्ट को कॉपी करने के विभिन्न तरीकों को सूचीबद्ध करता हूं, कल्पना करें कि आपके पास नीचे की वस्तु है और उस की एक गहरी प्रतिलिपि रखना चाहते हैं:

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
अंडरस्कोर में क्लोन वर्तमान संस्करण में एक गहरा क्लोन नहीं है
Rogelio

धन्यवाद। अंडरस्कोर के लिए नए डॉक के रूप में ... clone_.clone (ऑब्जेक्ट) प्रदान की गई ऑब्जेक्ट की उथली-प्रतिलिपि क्लोन बनाएं। किसी भी नेस्टेड ऑब्जेक्ट या सरणियों को संदर्भ द्वारा कॉपी किया जाएगा, डुप्लिकेट नहीं। _.clone ({नाम: 'मो'}); => {नाम: 'मो'};
अलिर्ज़ा

59
Object.assignकरता नहीं गहरी कॉपी। उदाहरण: var x = { a: { b: "c" } }; var y = Object.assign({}, x); x.a.b = "d"। यदि यह गहरी नकल थी, y.a.bतब भी होगी c, लेकिन अभी है d
केबीए

8
Object.assign () केवल गुणों का पहला स्तर क्लोन करता है!
११:१३ बजे ११:

5
क्लोनो () फ़ंक्शन क्या है?
पास्टरेलो

53

मुझे पता है कि यह एक पुरानी पोस्ट है, लेकिन मैंने सोचा कि यह अगले व्यक्ति के लिए कुछ मदद कर सकता है जो साथ ठोकर खाता है।

जब तक आप किसी वस्तु को किसी वस्तु को निर्दिष्ट नहीं करते हैं, वह स्मृति में कोई संदर्भ नहीं रखती है। तो एक वस्तु बनाने के लिए जिसे आप अन्य वस्तुओं के बीच साझा करना चाहते हैं, आपको एक कारखाना बनाना होगा जैसे:

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

16
यह उत्तर वास्तव में प्रासंगिक नहीं है क्योंकि प्रश्न यह है: उदाहरण दिया गया है कि कोई कैसे प्रतिलिपि बनाता है c जिसे कारखाने के बारे में पता नहीं है या कारखाने का उपयोग नहीं करना चाहता है। फैक्ट्री का उपयोग न करने का कारण यह हो सकता है कि इंस्टेंटेशन बी के बाद अतिरिक्त डेटा (जैसे उपयोगकर्ता इनपुट) के साथ आरंभ किया गया हो।
नोएल अब्राहम

12
यह सच है कि यह वास्तव में सवाल का जवाब नहीं है, लेकिन मुझे लगता है कि यह महत्वपूर्ण है कि यह यहां हो क्योंकि यह उस सवाल का जवाब है जिस पर मुझे संदेह है कि यहां आने वाले कई लोग पूछने के लिए वास्तव में हैं।
अर्धविराम

8
क्षमा करें दोस्तों, मुझे सच में समझ नहीं आता कि इतने सारे अपवित्र क्यों हैं। ऑब्जेक्ट को क्लोन करना एक बहुत स्पष्ट अवधारणा है, आप ANOTHER ऑब्जेक्ट से एक ऑब्जेक्ट कोन करते हैं, और इसका कारखाना पैटर्न के साथ एक नया निर्माण करने के लिए बहुत कुछ नहीं है।
खुलता है

2
जबकि यह पूर्वनिर्धारित वस्तुओं के लिए काम करता है, इस तरह से "क्लोनिंग" मूल वस्तु में जोड़े गए नए गुणों को नहीं पहचान पाएगा। यदि आप a बनाते हैं, तो a में एक नई प्रॉपर्टी जोड़ें, फिर b बनाएं। b के पास नई संपत्ति नहीं होगी। अनिवार्य रूप से कारखाना पैटर्न नए गुणों के लिए अपरिवर्तनीय है। यह प्रतिमान क्लोनिंग नहीं है। देखें: jsfiddle.net/jzumbrun/42xejnbx
जॉन

1
मुझे लगता है कि यह अच्छी सलाह है, आम तौर पर, उपयोग करने के बजाय const defaultFoo = { a: { b: 123 } };आप जा सकते हैं const defaultFoo = () => ({ a: { b: 123 } };और आपकी समस्या हल हो गई है। हालांकि, यह वास्तव में सवाल का जवाब नहीं है। यह सवाल पर टिप्पणी के रूप में अधिक समझदार हो सकता है, पूर्ण उत्तर नहीं।
Qaribou

48

यदि आप इसका उपयोग कर रहे हैं, तो Underscore.js लाइब्रेरी में एक क्लोन विधि है।

var newObject = _.clone(oldObject);

24
लॉश में एक क्लोनडिप विधि है, यह इसे गहरा बनाने के लिए क्लोन करने के लिए एक और परम का भी समर्थन करता है: लॉश एड डॉक्स#clone और लॉश.com
docs#

12
@opensas ने सहमति व्यक्त की। लोदश आमतौर पर अंडरस्कोर से बेहतर है
nha

7
मैं इसे और अन्य सभी उत्तरों को हटाने की वकालत करता हूं जो एक उपयोगिता पुस्तकालय की .clone(...)विधि के लिए केवल एक-पंक्ति संदर्भ हैं । प्रत्येक प्रमुख पुस्तकालय में उनके पास होगा, और दोहराया संक्षिप्त गैर-विस्तृत उत्तर अधिकांश आगंतुकों के लिए उपयोगी नहीं हैं, जो उस विशेष पुस्तकालय का उपयोग नहीं करेंगे।
जेरेमी बैंक्स

41

यहां ऊपर दिए गए ConroyP के उत्तर का एक संस्करण दिया गया है, भले ही काम करने वाले के लिए आवश्यक पैरामीटर हों:

//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 कम कुशल है? यदि आपकी वस्तुएं छोटी हैं और आप उन्हें टन नहीं करते हैं तो लगभग 1000 टन वस्तुतः कुछ भी नहीं है।
मशीनगॉस्ट

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
क्लोन / कॉपी और इनहेरिटेंस के बीच अंतर यह है कि, - आपके उदाहरण का उपयोग करते हुए, जब मैं पुराने ऑबजेक्ट की संपत्ति को बदलता हूं, तो न्यूऑबजेक्ट में संपत्ति भी बदल जाती है। यदि आप एक प्रतिलिपि बनाते हैं, तो आप वह कर सकते हैं जो आप पुरानेObject के साथ चाहते हैं।
Ridcully

13
यह hasOwnProperty की जांच को तोड़ देगा ताकि किसी वस्तु को क्लोन करने के लिए यह एक बहुत ही आसान तरीका हो और आपको अप्रत्याशित परिणाम देगा।
Corban Brook Brook

var extendObj = function(childObj, parentObj) { var tmpObj = function () {} tmpObj.prototype = parentObj.prototype; childObj.prototype = new tmpObj(); childObj.prototype.constructor = childObj; };... davidshariff.com/blog/javascript-inheritance-patterns
कोडी

22

लोडश में एक अच्छा _.cloneDeep (मान) विधि है:

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

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

5
मैं इसे और अन्य सभी उत्तरों को हटाने की वकालत करता हूं जो एक उपयोगिता पुस्तकालय की .clone(...)विधि के लिए केवल एक-पंक्ति संदर्भ हैं । प्रत्येक प्रमुख पुस्तकालय में उनके पास होगा, और दोहराया संक्षिप्त गैर-विस्तृत उत्तर अधिकांश आगंतुकों के लिए उपयोगी नहीं हैं, जो उस विशेष पुस्तकालय का उपयोग नहीं करेंगे।
जेरेमी बैंक्स

उपयोग करने का एक आसान तरीका है _.merge({}, objA)। यदि केवल लॉश ने पहले स्थान पर वस्तुओं को म्यूट नहीं किया है, तो cloneफ़ंक्शन आवश्यक नहीं होगा।
रीब

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

2
नोड 9 में, JSON.parse (JSON.stringify (arrayOfAbout5KFlatObjects)) _.deepClone (arrayOfAbout5KFlatObjects) की तुलना में बहुत तेज़ है।
डैन डेस्केल्सस्कु

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

17
विधि के साथ समस्या यह है कि यदि आपके पास ओब्ज के भीतर उप-ऑब्जेक्ट हैं, तो उनके संदर्भ क्लोन किए जाएंगे, न कि प्रत्येक उप ऑब्जेक्ट के मान।
कमारेई

1
बस इसे पुनरावर्ती बनाएं ताकि उप वस्तुओं को गहराई से क्लोन किया जा सके।
फिएटजफ

बस जिज्ञासु ... अभ्यस्त क्लोन चर होगा मूल वस्तु के गुणों के लिए संकेत? क्योंकि यह कोई नई स्मृति आवंटन नहीं लगता है
रूपेश पटेल

3
हाँ। यह सिर्फ एक उथली प्रतिलिपि है, इसलिए क्लोन मूल ऑब्जेक्ट द्वारा इंगित की गई सटीक समान वस्तुओं को इंगित करेगा।
मार्क सिडेड

यह कोई उत्तर नहीं है। Your'e का शाब्दिक अर्थ किसी वस्तु को किसी अन्य वस्तु के संदर्भ में भरना है। स्रोत ऑब्जेक्ट में परिवर्तन करने से "क्लोन" में परिवर्तन होगा।
शॉन व्हेनरी

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 6 वें संस्करण , 2015) की प्रतिलिपि बनाएँ :

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 क्लोनर गैर-संख्यात्मक गुणों को छोड़ देता है। निम्नलिखित परीक्षण कई ब्राउज़रों पर इन बिंदुओं को दर्शाते हैं:

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
जैसा कि अन्य लोगों ने रेजिग के जवाब में टिप्पणी की है, यदि आप किसी सरणी-जैसी वस्तु को बदलना चाहते हैं, तो आप
एक्सटेंशन

15

मेरे पास दो अच्छे उत्तर हैं जो इस बात पर निर्भर करते हैं कि आपका उद्देश्य "सादे पुराने जावास्क्रिप्ट ऑब्जेक्ट" को क्लोन करना है या नहीं।

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

सादे पुराने जावास्क्रिप्ट ऑब्जेक्ट्स के लिए, आधुनिक रनटाइम में किसी ऑब्जेक्ट को क्लोन करने का एक अच्छा और सही तरीका काफी सरल है:

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

ध्यान दें कि स्रोत ऑब्जेक्ट शुद्ध JSON ऑब्जेक्ट होना चाहिए। यह कहना है, इसके सभी नेस्टेड गुण स्केलर (जैसे बूलियन, स्ट्रिंग, सरणी, ऑब्जेक्ट, आदि) होने चाहिए। किसी भी फ़ंक्शन या विशेष ऑब्जेक्ट जैसे RegExp या दिनांक का क्लोन नहीं किया जाएगा।

क्या यह कुशल है? धत्त हां। हमने क्लोनिंग के सभी तरीकों की कोशिश की है और यह सबसे अच्छा काम करता है। मुझे यकीन है कि कुछ निनजा एक तेज़ विधि को जोड़ सकते हैं। लेकिन मुझे संदेह है कि हम सीमांत लाभ के बारे में बात कर रहे हैं।

यह दृष्टिकोण सरल और लागू करने में आसान है। इसे एक सुविधा फ़ंक्शन में लपेटें और यदि आपको वास्तव में कुछ लाभ को निचोड़ने की आवश्यकता है, तो बाद के समय के लिए जाएं।

अब, गैर-सादे जावास्क्रिप्ट वस्तुओं के लिए, वास्तव में सरल उत्तर नहीं है। वास्तव में, जावास्क्रिप्ट कार्यों और आंतरिक वस्तु स्थिति की गतिशील प्रकृति के कारण नहीं हो सकता है। कार्यों के साथ एक JSON संरचना को डीप क्लोन करना आपको उन कार्यों और उनके आंतरिक संदर्भ को फिर से बनाने की आवश्यकता है। और जावास्क्रिप्ट बस ऐसा करने का एक मानकीकृत तरीका नहीं है।

ऐसा करने का सही तरीका, एक बार फिर, एक सुविधा पद्धति के माध्यम से है जिसे आप अपने कोड के भीतर घोषित करते हैं और पुन: उपयोग करते हैं। सुविधा पद्धति को अपनी स्वयं की वस्तुओं की कुछ समझ के साथ संपन्न किया जा सकता है ताकि आप नई वस्तु के भीतर ग्राफ को ठीक से बना सकें।

हमने अपना लिखा है, लेकिन जो सबसे अच्छा सामान्य दृष्टिकोण मैंने देखा है, वह यहाँ कवर किया गया है:

http://davidwalsh.name/javascript-clone

यह सही विचार है। लेखक (डेविड वाल्श) ने सामान्यीकृत कार्यों के क्लोनिंग पर टिप्पणी की है। यह कुछ ऐसा है जिसे आप अपने उपयोग के मामले के आधार पर चुन सकते हैं।

मुख्य विचार यह है कि आपको प्रति-कार्य के आधार पर अपने कार्यों (या प्रोटोटाइप वर्गों, इसलिए बोलना) की तात्कालिकता को विशेष रूप से संभालना होगा। यहाँ, उन्होंने RegExp और Date के लिए कुछ उदाहरण दिए हैं।

न केवल यह कोड संक्षिप्त है, बल्कि यह बहुत पठनीय है। इसका विस्तार करना बहुत आसान है।

क्या यह कुशल है? धत्त हां। यह देखते हुए कि लक्ष्य एक सच्ची गहरी-प्रतिरूप का उत्पादन करना है, तो आपको स्रोत ऑब्जेक्ट ग्राफ के सदस्यों को चलना होगा। इस दृष्टिकोण के साथ, आप वास्तव में किस बच्चे के सदस्यों का इलाज कर सकते हैं और कस्टम प्रकारों को मैन्युअल रूप से कैसे संभाल सकते हैं।

तो यह तूम गए वहाँ। दो दृष्टिकोण। मेरे विचार से दोनों ही कुशल हैं।


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

मैं यहां सबसे बड़े वोटों के जवाब से असहमत हूं । एक रिकर्सिव दीप क्लोन है बहुत तेजी से JSON.parse (JSON.stringify (obj)) दृष्टिकोण का उल्लेख किया।

  • Jsperf ने इसे यहां नंबर एक पर रखा: 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());शून्य के लिए जाँच करने के बाद कुछ जोड़ने पर विचार करें
लुइस

वृत्ताकार संदर्भ पर दुर्घटना।
हैरी

नवीनतम स्थिर फ़ायरफ़ॉक्स में, यह Jsben.ch लिंक पर अन्य रणनीतियों की तुलना में अधिक है, जो परिमाण या अधिक के क्रम से है। यह दूसरों को गलत दिशा में मारता है।
WBT

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 या ट्रांसपाइलर का उपयोग कर सकते हैं ।

विशेषताएं:

  • नकल करते समय गेट्टर / सेटर को ट्रिगर न करें।
  • गेटटर / सेटर को संरक्षित करता है।
  • प्रोटोटाइप informations संरक्षित करता है।
  • दोनों वस्तु-शाब्दिक और कार्यात्मक 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;
};

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

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