आप जावास्क्रिप्ट में वस्तुओं के एक सरणी को कैसे क्लोन करते हैं?


420

... जहां प्रत्येक वस्तु में समान सरणी के भीतर अन्य वस्तुओं के संदर्भ भी हैं?

जब मैं पहली बार इस समस्या के साथ आया था तो मैं कुछ की तरह था

var clonedNodesArray = nodesArray.clone()

मौजूद होगा और कैसे जावास्क्रिप्ट में वस्तुओं को क्लोन करने के बारे में जानकारी के लिए खोज की। मुझे StackOverflow (बहुत ही @JohnResig द्वारा उत्तर दिया गया) पर एक सवाल मिला और उन्होंने बताया कि jQuery के साथ क्या कर सकते हैं

var clonedNodesArray = jQuery.extend({}, nodesArray);

किसी वस्तु का क्लोन बनाना। मैंने हालांकि यह कोशिश की, यह केवल सरणी में वस्तुओं के संदर्भों की प्रतिलिपि बनाता है। तो अगर मैं

nodesArray[0].value = "red"
clonedNodesArray[0].value = "green"

दोनों nodesArray का मान [0] और क्लोन किया गया NAAray [0] "हरा" हो जाएगा। फिर मैंने कोशिश की

var clonedNodesArray = jQuery.extend(true, {}, nodesArray);

जो किसी ऑब्जेक्ट को गहराई से कॉपी करता है, लेकिन मुझे क्रमशः फायरबग और ओपेरा ड्रैगनफ्लाई दोनों से " बहुत अधिक रिकर्सन " और " कंट्रोल स्टैक ओवरफ्लो " संदेश मिला।

आपको इसे कैसे करना होगा? क्या यह कुछ ऐसा है जो भी नहीं किया जाना चाहिए? क्या जावास्क्रिप्ट में ऐसा करने का पुन: प्रयोज्य तरीका है?

जवाबों:


106

आपकी उथली प्रति के साथ समस्या यह है कि सभी वस्तुओं का क्लोन नहीं है। हालांकि प्रत्येक वस्तु के संदर्भ प्रत्येक सरणी में अद्वितीय हैं, एक बार जब आप अंततः इसे पकड़ लेते हैं तो आप पहले की तरह ही उसी वस्तु के साथ काम कर रहे होते हैं। जिस तरह से आपने इसे क्लोन किया है, उसमें कुछ भी गलत नहीं है ... Array.slice () का उपयोग करके एक ही परिणाम होगा।

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

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

यदि आपको परिपत्र संदर्भ वाली वस्तुओं की एक सरणी की गहरी प्रतिलिपि की आवश्यकता है, तो मेरा मानना ​​है कि आपको अपनी विशिष्ट डेटा संरचना को संभालने के लिए अपनी खुद की विधि को कोड करना होगा, जैसे कि यह एक बहु-पास क्लोन है:

  1. राउंड एक पर, सभी ऑब्जेक्ट्स का एक क्लोन बनाएं जो एरे में अन्य ऑब्जेक्ट्स का संदर्भ न दें। प्रत्येक वस्तु की उत्पत्ति पर नज़र रखें।
  2. राउंड दो पर, ऑब्जेक्ट्स को एक साथ लिंक करें।

1
@PatrickdeKleijn उत्तर के लिए फिक्स्ड लिंक: web.archive.org/web/20140222022056/http://my.opera.com/…-
माइक सूजेंडेल

531

जब तक आपकी वस्तुओं में JSON-serializable सामग्री (कोई फ़ंक्शंस, नहीं Number.POSITIVE_INFINITY, आदि) शामिल हैं, तब तक सरणियों या ऑब्जेक्ट्स को क्लोन करने के लिए किसी लूप की आवश्यकता नहीं है। यहाँ एक शुद्ध वेनिला एक-लाइन समाधान है।

var clonedArray = JSON.parse(JSON.stringify(nodesArray))

नीचे दी गई टिप्पणियों को संक्षेप में बताने के लिए, इस दृष्टिकोण का प्राथमिक लाभ यह है कि यह केवल सरणी ही नहीं बल्कि सरणी की सामग्री को भी क्लोन करता है। प्राथमिक डाउनसाइड केवल JSON-serializable सामग्री पर काम करने की इसकी सीमा है, और यह प्रदर्शन है (जो एक sliceआधारित दृष्टिकोण से काफी खराब है )।


118
यह JSON डेटा के लिए काम कर सकता है, लेकिन यदि आपके सरणी में ऑब्जेक्ट्स के कोई फ़ंक्शन या इंस्टेंसेस हैं, तो उनके लिए अलविदा कहें।
sp0rkyd0rky

12
सावधान रहें यदि आपके पास एक ऐसा सरणी है जिसमें मूल्य इन्फिनिटी है। यह मान नष्ट हो जाता है (बाद में शून्य हो जाता है)। ( jsfiddle.net/klickagent/ehm4bd3s )
klickagent.ch

13
यह सिर्फ आम तौर पर एक बुरा दृष्टिकोण जब तक आपके सरणी केवल पुरातन शामिल है, और / या वस्तुओं जो खुद ही स्ट्रिंग / संख्या / बूलियन पुरातन होते हैं (यहां तक कि है nullऔर undefinedसमस्याओं हो जाएगा, के बाद से JSON उन्हें समर्थन नहीं करता है)। इसके अलावा, यह एक बहुत ही कम कुशल संचालन है old_array.slice(0);, जो बेहतर और तेज दोनों तरह से काम करना चाहिए।
एक्सएमएल

2
यदि सरणी के ऑब्जेक्ट में DateTime है, तो DateTime के बजाय स्ट्रिंग को लौटा दिया जाएगा! नई तिथि == JSON.parse (JSON.stringify (नई तिथि))!
MarkosyanArtur

2
ओपी के प्रश्न में मुख्य पंक्ति, जिसका यह उत्तर पूरी तरह से नजरअंदाज करता है: ... जहां प्रत्येक वस्तु में समान सरणी के भीतर अन्य वस्तुओं के संदर्भ भी हैं?
एक्सएमएल

288

मैंने Object.assign के साथ ऑब्जेक्ट की एक सरणी का क्लोनिंग हल किया

const newArray = myArray.map(a => Object.assign({}, a));

या फैल सिंटैक्स के साथ भी कम

const newArray = myArray.map(a => ({...a}));

15
लेकिन अगर MyArray में डायनासोर का एक गुच्छा होता है, तो newArray में ऑब्जेक्ट्स का एक गुच्छा होता है। यह लंगड़ा है, क्या आप सहमत नहीं हैं?
मैथ्यू जेम्स डेविस

3
सबसे अच्छा तरीका है, क्योंकि यह वस्तुओं को जीवित रखता है, रथन को फिर JSON.parse (JSON.stringify (nodesArray) के साथ खो देता है)
13

14
आप बदल कर भी इस का समाधान कर सकते @MatthewJamesDavis {}साथ new Dinosaur()
आगरगरा

5
उथली प्रति नहीं गहरी प्रति
सुल्तान असलम

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

154

यदि आप सभी की जरूरत है एक उथले प्रति है, एक बहुत आसान तरीका है:

new_array = old_array.slice(0);

6
मुझे नहीं लगता कि आपको पास होना है 0, आप .slice()कम से कम क्रोम में वैसे भी कॉल कर सकते हैं
स्लफ

112
हालांकि यह वास्तव में काम नहीं करता है, है ना? मेरा मतलब है, यह इस सवाल का जवाब नहीं है कि वस्तुओं की एक सरणी को कैसे क्लोन किया जाए। यह एक सरल सरणी क्लोन करने के लिए समाधान है।
बूजदोज़

35
वास्तव में यह एक ऑब्जेक्ट सरणी के लिए काम नहीं करेगा। द्वारा दी गई सरणी sliceएक नई सरणी होगी लेकिन इसमें मूल सरणी ऑब्जेक्ट्स के संदर्भ होंगे।
सर्जियो ए।

4
यह केवल "जेनेरिक" इंट, स्ट्रिंग आदि के लिए काम करेगा, लेकिन वस्तुओं की एक सरणी के लिए नहीं।
स्टीफन मिशेव

5
यह वास्तव में क्लोन नहीं करता है वस्तुओं की सरणी के लिए, new_array के लिए अद्यतन भी old_array अद्यतन करेगा।
अनस

43

इस क्लोन को करने के लिए सबसे अच्छा और सबसे अद्यतित तरीका इस प्रकार है:

का उपयोग करते हुए ...ES6 प्रसार ऑपरेटर ।

यहाँ सबसे सरल उदाहरण है:

var clonedObjArray = [...oldObjArray];

इस तरह हम सरणी को अलग-अलग मानों में फैलाते हैं और इसे [] ऑपरेटर के साथ एक नए सरणी में डालते हैं।

यहां एक लंबा उदाहरण दिया गया है जो विभिन्न तरीकों को दिखाता है:

let objArray = [ {a:1} , {b:2} ];

let refArray = objArray; // this will just point to the objArray
let clonedArray = [...objArray]; // will clone the array

console.log( "before:" );
console.log( "obj array" , objArray );
console.log( "ref array" , refArray );
console.log( "cloned array" , clonedArray );

objArray[0] = {c:3};

console.log( "after:" );
console.log( "obj array" , objArray ); // [ {c:3} , {b:2} ]
console.log( "ref array" , refArray ); // [ {c:3} , {b:2} ]
console.log( "cloned array" , clonedArray ); // [ {a:1} , {b:2} ]


2
अच्छा आधुनिक उत्तर, जो पुराने ब्राउज़रों (जैसे IE 11) के साथ काम नहीं करेगा
Jealie

1
@ जेली मैं अनुमान लगाने जा रहा हूं कि किंगपिनक्स इस जवाब को लक्ष्य बना रहा है कि लोग एस्क 6 को ट्रांसलेटिंग कर रहे हैं, जो बेबल के साथ अधिक सार्वभौमिक रूप से उपयोगी है या आपके पास क्या है।
रफिन

61
यह सरणी में प्रत्येक ऑब्जेक्ट को नहीं, बल्कि केवल गहरी प्रतिलिपि बनाता है।
इनवो सेवेन जुले

31
@ ToivoSäwén ने जो कहा, उस पर अमल करने के लिए, यह सरणी में ऑब्जेक्ट्स को गहराई से कॉपी नहीं करेगा। यह अभी भी मूल वस्तुओं को संदर्भित करेगा इसलिए यदि आप उन्हें म्यूट करते हैं, तो यह मूल सरणी को भी प्रभावित करेगा।
जोएल किन्ज़ेल

3
यह केवल प्राथमिकताओं के लिए काम करता है। इसे आज़माएँ: objArray [0] .a = 3; और आप देखेंगे कि ऑब्जेक्ट का संदर्भ क्लोनड्रे में समान रहता है।
सर्जियो कोरीया

25

यह मेरे लिए काम करता है:

var clonedArray = $.map(originalArray, function (obj) {
                      return $.extend({}, obj);
                  });

और अगर आपको सरणी में वस्तुओं की गहरी प्रतिलिपि की आवश्यकता है:

var clonedArray = $.map(originalArray, function (obj) {
                      return $.extend(true, {}, obj);
                  });

1
ऐसा लग रहा है कि यह काम करेगा। मैं व्यापक jQuery के उपयोग से बचने की कोशिश कर रहा हूं, इसलिए मैं इसे अपनी स्थिति में उपयोग नहीं करूंगा, लेकिन एक लूप और इसके लिए ... काम करेगा।
bozdoz

19
$.evalJSON($.toJSON(origArray));

2
आप का उपयोग करने की आवश्यकता होगी jQuery json प्लग इन को इस का उपयोग करने के code.google.com/p/jquery-json
wmitchell

32
बिना JQ (आधुनिक ब्राउज़रों में ठीक):JSON.parse(JSON.stringify(origArray));
forresto

मुझे यह टिप्पणी उपयोगी लगी। मेरे कार्यान्वयन में मुझे उन वस्तुओं की एक सरणी की एक प्रतिलिपि बनाने की आवश्यकता थी जिनके पास नॉकआउट जेएस अवलोकन योग्य गुण थे। प्रतिलिपि को केवल मूल्यों की आवश्यकता थी, न कि अवलोकन-योग्य नेस की। JUST की एक प्रतिलिपि बनाने के लिए मैंने JSON.parse (ko.toJSON (OrigArray)) या ko.utils.parseJson (ko.toJSON (origArray)) का उपयोग किया। बस मेरे 2 सेंट और मेरे समाधान में आने में मेरी मदद करने के लिए धन्यवाद।
wededrop

6
JSON.parse(JSON.stringify(origArray));निश्चित रूप से सबसे सरल समाधान है।
yorkw

jQuery अक्सर अनावश्यक होता है। youmightnotneedjquery.com
ADJenks

9

नक्शा पुराने से नया सरणी बनाएगा (पुराने के संदर्भ के बिना) और मानचित्र के अंदर आप नई वस्तु बनाते हैं और गुणों पर पुनरावृति करते हैं (कुंजी) और नए ऑब्जेक्ट में गुण coresponding करने के लिए पुराने सरणी वस्तु से असाइन मान।

यह ऑब्जेक्ट्स की समान सरणी बनाएगा।

let newArray = oldArray.map(a => {
               let newObject = {};
               Object.keys(a).forEach(propertyKey => {
                    newObject[propertyKey] = a[propertyKey];
               });
               return newObject ;
});

8

मेरे पास ऐसा करने का एक सरल तरीका हो सकता है बिना दर्दनाक पुनरावृत्ति के और प्रश्न में वस्तु के सभी बारीक विवरणों को न जानने का। JQuery का उपयोग करना, बस अपनी वस्तु को jQuery का उपयोग करके JSON में परिवर्तित करें $.toJSON(myObjectArray), फिर अपना JSON स्ट्रिंग लें और किसी ऑब्जेक्ट पर वापस मूल्यांकन करें। BAM! किया और किया! समस्या सुलझ गयी। :)

var oldObjArray = [{ Something: 'blah', Cool: true }];
var newObjArray = eval($.toJSON(oldObjArray));

21
कुछ आधुनिक ब्राउज़रों में JSON पद्धति अंतर्निहित है, जिससे आप यह कर सकते हैं: JSON.parse (JSON.stringify (MY_ARRAY)) जो तेज होना चाहिए। अच्छा सुझाव।
निकोलस आर

1
और अगर वे json2 का उपयोग नहीं करते हैं , तो नहीं eval
कामरानिकस

यह भयानक प्रदर्शन है, लेकिन दुर्भाग्य से मैंने देखा सबसे अच्छा जवाब है: /
Dvid सिल्वा

उपयोगकर्ता डेटा के साथ कुछ भी नहीं निकालें। अधिमानतः कभी भी उपयोग न करें eval()। यह एक सुरक्षा जोखिम है।
ADJenks

8

मैं इस सवाल का जवाब दे रहा हूं क्योंकि "जावास्क्रिप्ट में वस्तुओं की एक सरणी क्लोनिंग" की समस्या का एक सरल और स्पष्ट समाधान प्रतीत नहीं होता है:

function deepCopy (arr) {
    var out = [];
    for (var i = 0, len = arr.length; i < len; i++) {
        var item = arr[i];
        var obj = {};
        for (var k in item) {
            obj[k] = item[k];
        }
        out.push(obj);
    }
    return out;
}

// test case

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

var copy = deepCopy(original);

// change value in copy
copy[0]['a'] = 'not 1';

// original[0]['a'] still equals 1

यह समाधान सरणी मानों को पुन: प्रसारित करता है, फिर ऑब्जेक्ट कुंजियों को पुनरावृत्त करता है, बाद वाले को एक नई वस्तु में सहेजता है और फिर उस नई वस्तु को एक नए सरणी में धकेलता है।

Jsfiddle देखें । नोट: सरणी के भीतर वस्तुओं के लिए एक सरल .slice()या [].concat()पर्याप्त नहीं है ।


उत्तर के लिए धन्यवाद, लेकिन आपको उत्तर की कमियों को उजागर करना चाहिए। यह तब काम नहीं करता जब वस्तुओं में वस्तुएं हों .. सही?
हर्ष

यह उथली प्रतिलिपि बनाएगा। गहरा नहीं
सुल्तान असलम

आपको कहीं पुनरावृत्ति जोड़ने की आवश्यकता है
DGoiko

6

JQuery का विस्तार ठीक काम कर रहा है, बस आपको यह निर्दिष्ट करने की आवश्यकता है कि आप किसी ऑब्जेक्ट के बजाय एक सरणी को क्लोन कर रहे हैं ( नोट करें [] के बजाय {} को विस्तार विधि के पैरामीटर के रूप में ):

var clonedNodesArray = jQuery.extend([], nodesArray);

2
हम्म, अगर आप इसे कम करते हैं, तो क्या आप ऐसा करने के बारे में टिप्पणी जोड़ सकते हैं? या आप पहले कोड की कोशिश कर सकते हैं और देख सकते हैं कि यह काम करता है या नहीं? धन्यवाद;)
स्टेफ

1
पहले एरे में किसी ऑब्जेक्ट को बदलने के बाद, दूसरे एरे में ऑब्जेक्ट को संशोधित किया जाता है, इसलिए यह ठीक नहीं है।
स्पिकोलिन

6

यह विधि बहुत सरल है और आप मूल सरणी को संशोधित किए बिना अपने क्लोन को संशोधित कर सकते हैं।

// Original Array
let array = [{name: 'Rafael'}, {name: 'Matheus'}];

// Cloning Array
let clone = array.map(a => {return {...a}})

// Editing the cloned array
clone[1].name = 'Carlos';


console.log('array', array)
// [{name: 'Rafael'}, {name: 'Matheus'}]

console.log('clone', clone)
// [{name: 'Rafael'}, {name: 'Carlos'}]


1
यह एक उथले प्रति दो स्तर नीचे है, जबकि करता है [...oldArray]और oldArray.slice(0)एक उथले करना एक स्तर गहरी कॉपी। तो यह सुपर उपयोगी है, लेकिन एक वास्तविक पूर्ण गहरी क्लोन नहीं है।
बेन व्हीलर

सच गहरी क्लोन का उपयोग कर किया जा सकता है lodash.clonedeepNPM से
revelt

5

जैसा कि डैनियल ल्यू ने कहा, चक्रीय रेखांकन में कुछ समस्याएं हैं। अगर मुझे यह समस्या थी तो मैं या तो विशेष जोड़ूंगाclone() समस्याग्रस्त वस्तुओं में तरीके जोड़ूँगा या याद रखूँगा कि मैंने किन वस्तुओं को पहले ही कॉपी कर लिया है।

मैं इसे एक चर के साथ करूँगा copyCountजो आपके कोड में कॉपी होने पर हर बार 1 से बढ़ जाता है। copyCountवर्तमान प्रतिलिपि-प्रक्रिया की तुलना में कम ऑब्जेक्ट पर प्रतिलिपि बनाई गई है। यदि नहीं, तो प्रति, जो पहले से मौजूद है, को संदर्भित किया जाना चाहिए। यह मूल से इसकी प्रति से लिंक करना आवश्यक बनाता है।

अभी भी एक समस्या है: मेमोरी। यदि आपके पास यह संदर्भ एक वस्तु से दूसरी वस्तु तक है, तो संभावना है कि ब्राउज़र उन वस्तुओं को मुक्त नहीं कर सकता है, क्योंकि वे हमेशा कहीं से संदर्भित होते हैं। आपको एक दूसरा पास बनाना होगा जहाँ आप सभी कॉपी-रेफरेंस को Null में सेट करते हैं। (यदि आप ऐसा करते हैं, तो आपके पास copyCountएक बूलियन isCopiedहोना पर्याप्त नहीं होगा, क्योंकि आप दूसरे पास में मान को रीसेट कर सकते हैं।)


4

Array.slice का उपयोग किसी सरणी या किसी सरणी के भाग को कॉपी करने के लिए किया जा सकता है .. http://www.devguru.com/Technologies/Ecmascript/Quickref/Slice.html यह तार और संख्याओं के साथ काम करेगा .. - में एक स्ट्रिंग बदलना एक सरणी दूसरे को प्रभावित नहीं करेगी - लेकिन वस्तुओं को अभी भी संदर्भ द्वारा कॉपी किया जाता है ताकि एक सरणी में संदर्भित वस्तुओं में परिवर्तन दूसरे सरणी पर प्रभावित हो।

यहाँ जावास्क्रिप्ट पूर्ववत प्रबंधक का एक उदाहरण दिया गया है जो इसके लिए उपयोगी हो सकता है: http://www.ridgway.co.za/archive/2007/11/07/simple-javascript-undo-manager-for-dtos.aspx


मुझे पता है। इसका कारण मैं इसे लागू करना चाहता था क्योंकि मैं एक सीएसपी समस्या को हल करने की कोशिश कर रहा हूं। मैंने सोचा था कि बैकट्रैकिंग को लागू करने के तरीकों में से एक हो सकता है जैसे "स्नैपशॉट लेना" वैरिएबल के असाइनमेंट की स्थिति द्वारा ... ऐसे स्नैपशॉट को स्टैक में क्लोन करना।
वाल्क

... और ठीक है, यह वास्तव में एक बहुत बुरा विचार हो सकता है।
वाल्क

उस दृष्टिकोण में अन्य सिंक्रनाइज़ेशन जटिलताएं हो सकती हैं :) .. आप कैसे जानते हैं कि स्नैपशॉट लेते समय सरणी को बदला नहीं जा रहा है ?
अंक

एक लेख के लिए एक लिंक जोड़ा गया जहाँ लेखक ने जावास्क्रिप्ट का उपयोग करते हुए एक सरल पूर्व प्रबंधक को लागू किया है ..
चिह्न

4

मेरा दृष्टिकोण:

var temp = { arr : originalArray };
var obj = $.extend(true, {}, temp);
return obj.arr;

मुझे मूल सरणी का एक अच्छा, साफ, गहरा क्लोन देता है - मूल वस्तुओं में से किसी के साथ वापस मूल :-)


यह jquery का उपयोग करके सबसे अच्छा समाधान है। छोटा एवं सुन्दर।
जॉन हेन्केल

1
मैंने एक प्रदर्शन परीक्षण किया और यह समाधान JSON.stringify समाधान की तुलना में लगभग 2x अधिक तेज़ प्रतीत होता है।
मीहोकोज़

4

लॉश में cloneDeepइस उद्देश्य के लिए कार्य है:

var objects = [{ 'a': 1 }, { 'b': 2 }];
var deep = _.cloneDeep(objects);

4

यदि आप JSON.parse (JSON.stringify (आपका {} या [])) का गहन क्लोन उपयोग लागू करना चाहते हैं

const myObj ={
    a:1,
    b:2,
    b:3
}

const deepClone=JSON.parse(JSON.stringify(myObj));
deepClone.a =12;
console.log("deepClone-----"+myObj.a);
const withOutDeepClone=myObj;
withOutDeepClone.a =12;
console.log("withOutDeepClone----"+myObj.a);


3

भूल जाना () (जेएस की सबसे दुरुपयोग विशेषता है और कोड को धीमा बनाता है) और टुकड़ा (0) (केवल साधारण डेटा के लिए काम करता है)

यह मेरे लिए सबसे अच्छा समाधान है:

Object.prototype.clone = function() {
  var myObj = (this instanceof Array) ? [] : {};
  for (i in this) {
    if (i != 'clone') {
        if (this[i] && typeof this[i] == "object") {
          myObj[i] = this[i].clone();
        } else 
            myObj[i] = this[i];
        } 
    }
  return myObj;
};

3

मैं इस समस्या से बहुत निराश था। जाहिरा तौर पर समस्या तब पैदा होती है जब आप एक सामान्य सरणी में $ .extend विधि को भेजते हैं। इसलिए, इसे ठीक करने के लिए, मैंने थोड़ा सा चेक जोड़ा, और यह जेनेरिक सरणियों, jQuery सरणियों और किसी भी ऑब्जेक्ट के साथ पूरी तरह से काम करता है।

jQuery.extend({
    deepclone: function(objThing) {
        // return jQuery.extend(true, {}, objThing);
        /// Fix for arrays, without this, arrays passed in are returned as OBJECTS! WTF?!?!
        if ( jQuery.isArray(objThing) ) {
            return jQuery.makeArray( jQuery.deepclone($(objThing)) );
        }
        return jQuery.extend(true, {}, objThing);
    },
});

उपयोग करें:

var arrNewArrayClone = jQuery.deepclone(arrOriginalArray);
// Or more simply/commonly
var arrNewArrayClone = $.deepclone(arrOriginalArray);

deepclone? मैं jquery-1.9.1 का उपयोग करता हूं और यह इस पद्धति का समर्थन नहीं करता है। क्या यह अधिक आधुनिक संस्करण की विधि है?
user5260143

@ user2783091 वह उस कार्य को जोड़ने के लिए JQuery का विस्तार कर रहा है। इसका कुछ नहीं है जो बॉक्स से बाहर आता है
जोर्ज एफजी

3

यह गहराई से सरणियों, वस्तुओं, नल और अन्य अदिश मानों को कॉपी करता है, और गैर-देशी कार्यों (जो कि बहुत ही असामान्य लेकिन संभव है) पर किसी भी गुण को गहराई से कॉपी करता है। (दक्षता के लिए, हम सरणियों पर गैर-संख्यात्मक गुणों को कॉपी करने का प्रयास नहीं करते हैं।)

function deepClone (item) {
  if (Array.isArray(item)) {
    var newArr = [];
    for (var i = item.length; i-- > 0;) {
      newArr[i] = deepClone(item[i]);
    }
    return newArr;
  }
  if (typeof item === 'function' && !(/\(\) \{ \[native/).test(item.toString())) {
    var obj;
    eval('obj = '+ item.toString());
    for (var k in item) {
      obj[k] = deepClone(item[k]);
    }
    return obj;
  }
  if (item && typeof item === 'object') {
    var obj = {};
    for (var k in item) {
      obj[k] = deepClone(item[k]);
    }
    return obj;
  }
  return item;
}

3

मैं नई ECMAScript 6 Object.assign विधि का उपयोग करता हूं :

let oldObject = [1,3,5,"test"];
let newObject = Object.assign({}, oldObject);

इस पद्धति का पहला तर्क है अपडेट होने का सरणी, हम एक खाली वस्तु पास करते हैं क्योंकि हम एक नई वस्तु रखना चाहते हैं।

हम इस वाक्यविन्यास का भी उपयोग कर सकते हैं, जो समान है लेकिन कम है:

let newObject = [...oldObject];

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

2

हम बहुआयामी सरणियों को क्लोन करने के लिए एक सरल पुनरावर्ती ऐरे विधि का आविष्कार कर सकते हैं। जबकि नेस्टेड सरणियों के भीतर ऑब्जेक्ट्स स्रोत सरणी में संबंधित ऑब्जेक्ट्स के लिए अपना संदर्भ रखते हैं, सरणियां नहीं होंगी।

Array.prototype.clone = function(){
  return this.map(e => Array.isArray(e) ? e.clone() : e);
};

var arr = [ 1, 2, 3, 4, [ 1, 2, [ 1, 2, 3 ], 4 , 5], 6 ],
    brr = arr.clone();
brr[4][2][1] = "two";
console.log(JSON.stringify(arr));
console.log(JSON.stringify(brr));


2

जावास्क्रिप्ट में, सरणी और ऑब्जेक्ट कॉपी मूल मूल्यों को बदलते हैं, इसलिए डीप कॉपी इसके लिए समाधान है।

एक गहरी प्रतिलिपि का मतलब वास्तव में एक नई सरणी बनाना और मूल्यों पर प्रतिलिपि बनाना है, क्योंकि जो कुछ भी होता है वह कभी भी मूल को प्रभावित नहीं करेगा।

JSON.parseऔर JSON.stringifyडीप कॉपी करने का सबसे अच्छा और सरल तरीका है। JSON.stringify()विधि एक JSON string.The करने के लिए JavaScript मूल्य धर्मान्तरितJSON.parse() JSON स्ट्रिंग में JSON स्ट्रिंग को पार्स करती है, स्ट्रिंग द्वारा वर्णित जावास्क्रिप्ट मान या ऑब्जेक्ट का निर्माण करती है।

// गहरा क्लोन

let a = [{ x:{z:1} , y: 2}];
let b = JSON.parse(JSON.stringify(a));
b[0].x.z=0

console.log(JSON.stringify(a)); //[{"x":{"z":1},"y":2}]
console.log(JSON.stringify(b)); // [{"x":{"z":0},"y":2}]

अधिक जानकारी के लिए: यहां पढ़ें


1
यह सबसे अच्छा उपाय है। धन्यवाद।
निकोले

1

jQuery के साथ:

var target= [];
$.each(source, function() {target.push( $.extend({},this));});

1

निम्नलिखित कोड पुनरावर्ती रूप से वस्तुओं और सरणी की गहरी नकल करेगा :

function deepCopy(obj) {
if (Object.prototype.toString.call(obj) === '[object Array]') {
    var out = [], i = 0, len = obj.length;
    for ( ; i < len; i++ ) {
        out[i] = arguments.callee(obj[i]);
    }
    return out;
}
if (typeof obj === 'object') {
    var out = {}, i;
    for ( i in obj ) {
        out[i] = arguments.callee(obj[i]);
    }
    return out;
}
return obj;
}

स्रोत


arguments.calleeसख्त मोड में उपलब्ध नहीं है और अन्यथा प्रदर्शन समस्याएं हैं।
ब्रेट ज़मीर

1

जावास्क्रिप्ट में गहरी क्लोनिंग के लिए कुछ सुरुचिपूर्ण तरीके

https://mootools.net/core/docs/1.6.0/Types/Object

https://scotch.io/bar-talk/copying-objects-in-javascript

1) वस्तुओं की क्लोनिंग के लिए एक वेनिला जावास्क्रिप्ट विधि

2) गहरी-क्लोन वस्तुओं के लिए JSON लाइब्रेरी का एक चतुर शोषण

3) jQuery के $ .extend () फ़ंक्शन का उपयोग करना

4) Mootools 'क्लोन () फ़ंक्शन का उपयोग करके क्लोन ऑब्जेक्ट्स


0

मुझे लगता है कि किसी भी जावास्क्रिप्ट संरचना को मुख्य रूप से उपयोग करने के लिए गहरी क्लोनिंग की एक सामान्य विधि लिखने में कामयाब रहा Object.createजो सभी आधुनिक ब्राउज़रों में समर्थित है। कोड इस प्रकार है:

function deepClone (item) {
  if (Array.isArray(item)) {
    var newArr = [];

    for (var i = item.length; i-- !== 0;) {
      newArr[i] = deepClone(item[i]);
    }

    return newArr;
  }
  else if (typeof item === 'function') {
    eval('var temp = '+ item.toString());
    return temp;
  }
  else if (typeof item === 'object')
    return Object.create(item);
  else
    return item;
}

Object.createitemवस्तु के प्रोटोटाइप के रूप में माना जाएगा , लेकिन यह क्लोनिंग से अलग है। यदि itemसंशोधित किया गया है, तो इसके "क्लोन" में परिवर्तन दिखाई देगा और इसके विपरीत। यह दृष्टिकोण काम नहीं करता है।
ब्रेट ज़मीर

0

वस्तुओं को क्लोन करने के लिए मैं सिर्फ ECMAScript 6 का सुझाव देने जा रहा था reduce():

const newArray=myArray.reduce((array, element)=>array.push(Object.assign({}, element)), []);

लेकिन स्पष्ट रूप से मुझे @dinodsaurus का उत्तर और भी अच्छा लगता है। मैं सिर्फ इस संस्करण को एक अन्य विकल्प के रूप में यहां रख रहा हूं, लेकिन व्यक्तिगत रूप से मैं map()@dinodsaurus द्वारा सुझाए गए अनुसार उपयोग करूंगा।


0

यदि आपके पास अंडरस्कोर या बैबेल है, तो यह निर्भर करता है कि एक सरणी के गहरे क्लोनिंग के विभिन्न तरीके के बेंचमार्क हैं।

https://jsperf.com/object-rest-spread-vs-clone/2

जैसे बबल सबसे तेज है।

var x = babel({}, obj)

0
       var game_popularity = [
            { game: "fruit ninja", popularity: 78 },
            { game: "road runner", popularity: 20 },
            { game: "maze runner", popularity: 40 },
            { game: "ludo", popularity: 75 },
            { game: "temple runner", popularity: 86 }
        ];
        console.log("sorted original array before clonning");
        game_popularity.sort((a, b) => a.popularity < b.popularity);
        console.log(game_popularity);


        console.log("clone using object assign");
        const cl2 = game_popularity.map(a => Object.assign({}, a));
        cl2[1].game = "clash of titan";
        cl2.push({ game: "logan", popularity: 57 });
        console.log(cl2);


        //adding new array element doesnt reflect in original array
        console.log("clone using concat");
        var ph = []
        var cl = ph.concat(game_popularity);

        //copied by reference ?
        cl[0].game = "rise of civilization";

        game_popularity[0].game = 'ping me';
        cl.push({ game: "angry bird", popularity: 67 });
        console.log(cl);

        console.log("clone using ellipses");
        var cl3 = [...game_popularity];
        cl3.push({ game: "blue whale", popularity: 67 });
        cl3[2].game = "harry potter";
        console.log(cl3);

        console.log("clone using json.parse");
        var cl4 = JSON.parse(JSON.stringify(game_popularity));
        cl4.push({ game: "home alone", popularity: 87 });
        cl4[3].game ="lockhead martin";
        console.log(cl4);

        console.log("clone using Object.create");
        var cl5 = Array.from(Object.create(game_popularity));
        cl5.push({ game: "fish ville", popularity: 87 });
        cl5[3].game ="veto power";
        console.log(cl5);


        //array function
        console.log("sorted original array after clonning");
        game_popularity.sort((a, b) => a.popularity < b.popularity);
        console.log(game_popularity);


        console.log("Object.assign deep clone object array");
        console.log("json.parse deep clone object array");
        console.log("concat does not deep clone object array");
        console.log("ellipses does not deep clone object array");
        console.log("Object.create does not deep clone object array");


        Output:


        sorted original array before clonning
        [ { game: 'temple runner', popularity: 86 },
        { game: 'fruit ninja', popularity: 78 },
        { game: 'ludo', popularity: 75 },
        { game: 'maze runner', popularity: 40 },
        { game: 'road runner', popularity: 20 } ]
        clone using object assign
        [ { game: 'temple runner', popularity: 86 },
        { game: 'clash of titan', popularity: 78 },
        { game: 'ludo', popularity: 75 },
        { game: 'maze runner', popularity: 40 },
        { game: 'road runner', popularity: 20 },
        { game: 'logan', popularity: 57 } ]
        clone using concat
        [ { game: 'ping me', popularity: 86 },
        { game: 'fruit ninja', popularity: 78 },
        { game: 'ludo', popularity: 75 },
        { game: 'maze runner', popularity: 40 },
        { game: 'road runner', popularity: 20 },
        { game: 'angry bird', popularity: 67 } ]
        clone using ellipses
        [ { game: 'ping me', popularity: 86 },
        { game: 'fruit ninja', popularity: 78 },
        { game: 'harry potter', popularity: 75 },
        { game: 'maze runner', popularity: 40 },
        { game: 'road runner', popularity: 20 },
        { game: 'blue whale', popularity: 67 } ]
        clone using json.parse
        [ { game: 'ping me', popularity: 86 },
        { game: 'fruit ninja', popularity: 78 },
        { game: 'harry potter', popularity: 75 },
        { game: 'lockhead martin', popularity: 40 },
        { game: 'road runner', popularity: 20 },
        { game: 'home alone', popularity: 87 } ]
        clone using Object.create
        [ { game: 'ping me', popularity: 86 },
        { game: 'fruit ninja', popularity: 78 },
        { game: 'harry potter', popularity: 75 },
        { game: 'veto power', popularity: 40 },
        { game: 'road runner', popularity: 20 },
        { game: 'fish ville', popularity: 87 } ]
        sorted original array after clonning
        [ { game: 'ping me', popularity: 86 },
        { game: 'fruit ninja', popularity: 78 },
        { game: 'harry potter', popularity: 75 },
        { game: 'veto power', popularity: 40 },
        { game: 'road runner', popularity: 20 } ]

        Object.assign deep clone object array
        json.parse deep clone object array
        concat does not deep clone object array
        ellipses does not deep clone object array
        Object.create does not deep clone object array
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.