परिचय: सीधा असाइनमेंट क्यों एक जाल है?
\nकल्पना करें कि आप एक नोट्स ऐप बना रहे हैं। उपयोगकर्ता एक कार्ड बनाता है जिसमें शीर्षक और टेक्स्ट होता है, फिर वह उसकी कॉपी बनाकर उसमें थोड़ा बदलाव करना चाहता है। आप लिखते हैं:
\nconst original = { title: 'मेरी योजना', text: 'दूध खरीदना' };\nconst copy = original;\ncopy.title = 'नई योजना';\nconsole.log(original.title); // 'नई योजना' — ओह!\nयह स्थिति जानी-पहचानी लगती है? अगर हाँ, तो आप JavaScript में ऑब्जेक्ट की मुख्य विशेषता से टकराए हैं: वे रेफरेंस द्वारा पास होते हैं। copy = original असाइनमेंट कोई नया ऑब्जेक्ट नहीं बनाता, बल्कि उसी मेमोरी लोकेशन की एक रेफरेंस कॉपी करता है। copy में कोई भी बदलाव original को प्रभावित करेगा।
Stack Overflow पर सवाल "How do I correctly clone a JavaScript object?" ने हज़ारों व्यूज़ और दर्जनों जवाब जुटाए हैं। यह शुरुआती और अनुभवी डेवलपर्स दोनों के लिए सबसे आम समस्याओं में से एक है। इस लेख में हम JavaScript में ऑब्जेक्ट क्लोनिंग के सभी तरीकों को समझेंगे, सरल से लेकर उन्नत तक, और पता लगाएंगे कि किस स्थिति में कौन सा तरीका सबसे अच्छा है।
\n\nशैलो कॉपी (Shallow copy): तेज़ और आसान
\nशैलो कॉपी एक नया ऑब्जेक्ट बनाती है, लेकिन नेस्टेड ऑब्जेक्ट्स (एरे, अन्य ऑब्जेक्ट्स) के लिए केवल रेफरेंस कॉपी करती है। यह फ्लैट स्ट्रक्चर के लिए आदर्श है, लेकिन डीप स्ट्रक्चर के लिए खतरनाक है।
\n\nतरीका 1: Spread ऑपरेटर (…)
\nसबसे आधुनिक और पढ़ने में आसान तरीका:
\nconst original = { name: 'अन्ना', age: 25 };\nconst clone = { ...original };\nclone.age = 30;\nconsole.log(original.age); // 25 — सब ठीक है!\nफायदे: छोटा सिंटैक्स, एरे और ऑब्जेक्ट दोनों के साथ काम करता है। नुकसान: मेथड्स (फंक्शन) और सिंबल प्रॉपर्टीज को कॉपी नहीं करता।
\n\nतरीका 2: Object.assign()
\nटॉप-लेवल पर बिना रेफरेंस के ऑब्जेक्ट कॉपी करने का क्लासिक तरीका:
\nconst source = { a: 1, b: { c: 2 } };\nconst target = Object.assign({}, source);\ntarget.a = 100; // source.a नहीं बदलेगा\ntarget.b.c = 999; // source.b.c भी बदल जाएगा — shallow!\nयह तरीका विशेष रूप से तब उपयोगी है जब आपको कई ऑब्जेक्ट्स को मर्ज करना हो: Object.assign({}, obj1, obj2)।
तरीका 3: for…in लूप
\nपुराना लेकिन अभी भी काम करने वाला तरीका। मैकेनिज्म को समझने के लिए उपयोगी:
\nfunction shallowClone(obj) {\n const clone = {};\n for (let key in obj) {\n if (obj.hasOwnProperty(key)) {\n clone[key] = obj[key];\n }\n }\n return clone;\n}\nआज इसका उपयोग कम होता है, लेकिन यह अच्छी तरह दिखाता है कि मैन्युअली ऑब्जेक्ट क्लोनिंग कैसे काम करती है।
\n\nडीप कॉपी (Deep copy): जब सब कुछ चाहिए
\nअगर आपके ऑब्जेक्ट में नेस्टेड ऑब्जेक्ट्स, एरे या डेट्स हैं, तो शैलो कॉपी आपको निराश करेगी। डीप क्लोनिंग js की ज़रूरत है।
\n\nतरीका 4: JSON.parse + JSON.stringify
\nसबसे लोकप्रिय "हैक":
\nconst original = { \n name: 'पीटर', \n address: { city: 'मॉस्को', street: 'टावर्सकाया' },\n date: new Date()\n};\nconst clone = JSON.parse(JSON.stringify(original));\nclone.address.city = 'सेंट पीटर्सबर्ग';\nconsole.log(original.address.city); // 'मॉस्को' — शाबाश!\nलेकिन कुछ खामियाँ हैं: यह तरीका फंक्शन, undefined, Symbol को खो देता है, और Date को स्ट्रिंग में बदल देता है। सरल डेटा के लिए ठीक है, जटिल के लिए नहीं।
तरीका 5: structuredClone() — नया स्टैंडर्ड
\n2022 से JavaScript में बिल्ट-इन मेथड structuredClone आया है:
\nconst original = { \n scores: [10, 20, 30], \n meta: { level: 'easy' },\n date: new Date()\n};\nconst clone = structuredClone(original);\nclone.meta.level = 'hard';\nconsole.log(original.meta.level); // 'easy'\nफायदे: Date, Map, Set, ArrayBuffer, रिकर्सिव रेफरेंस को सपोर्ट करता है। नुकसान: फंक्शन, DOM-एलिमेंट्स, Error को सपोर्ट नहीं करता। काम करता है