परिचय: यह सवाल Stack Overflow पर हजारों बार क्यों देखा गया
\n\nजिसने भी कभी जावास्क्रिप्ट में लिखा है, वह ऐरे से जरूर मिला होगा। वे हर जगह हैं: उत्पादों की सूची, कार्यों की कतार, उपयोगकर्ता की गतिविधि का इतिहास। और देर-सबेर यह सवाल उठता है: "जावास्क्रिप्ट में ऐरे की शुरुआत में एलिमेंट कैसे जोड़ें?" Stack Overflow पर इस सवाल को लाखों बार देखा गया है, और इसके दर्जनों जवाब हैं। क्यों? क्योंकि स्पष्ट सादगी के पीछे ज्ञान की एक पूरी परत छिपी है: प्रदर्शन से लेकर इंजन की आंतरिक संरचना तक।
\n\nइस लेख में हम केवल unshift() नहीं दिखाएंगे। हम "अंदर की बात" देखेंगे: V8 इंजन शुरुआत में इंसर्शन को कैसे संभालता है, क्यों unshift push से धीमा हो सकता है, और विभिन्न परिदृश्यों के लिए कौन से विकल्प मौजूद हैं। चलिए शुरू करते हैं!
बुनियादी तरीका: unshift() मेथड
\n\nसबसे स्पष्ट और सामान्य तरीका बिल्ट-इन मेथड unshift() का उपयोग करना है। यह ऐरे की शुरुआत में एक या अधिक एलिमेंट जोड़ता है और ऐरे की नई लंबाई लौटाता है।
let fruits = ['banana', 'orange'];\nlet newLength = fruits.unshift('apple');\nconsole.log(fruits); // ['apple', 'banana', 'orange']\nconsole.log(newLength); // 3\n\nआप एक साथ कई एलिमेंट जोड़ सकते हैं:
\n\nlet numbers = [3, 4, 5];\nnumbers.unshift(1, 2);\nconsole.log(numbers); // [1, 2, 3, 4, 5]\n\nयहीं पर हम रुक सकते थे। लेकिन आइए समझें कि जब हम unshift() कॉल करते हैं तो अंदर क्या होता है।
unshift() अंदर से कैसे काम करता है: V8 पर एक नज़र
\n\nजावास्क्रिप्ट में ऐरे C की तरह सिर्फ मेमोरी का एक सतत ब्लॉक नहीं है। आधुनिक इंजनों (Chrome/Node.js में V8, Firefox में SpiderMonkey) में ऐरे को दो तरीकों से लागू किया जा सकता है:
\n\n- \n
- Fast elements (पैक्ड) — C-शैली की तरह सतत बफर। इंडेक्स द्वारा पढ़ने और लिखने के लिए इष्टतम। \n
- Dictionary elements (स्पार्स) — हैश टेबल। जब ऐरे "छिद्रपूर्ण" (इंडेक्स में गैप) हो जाता है या बहुत बड़ा हो जाता है तब उपयोग किया जाता है। \n
जब आप fast-ऐरे पर unshift() कॉल करते हैं, तो इंजन निम्नलिखित करता है:
- \n
- जोड़े जाने वाले एलिमेंट की संख्या के लिए नई मेमोरी आवंटित करता है (या मौजूदा को शिफ्ट करता है)। \n
- सभी मौजूदा एलिमेंट को n पोजीशन दाईं ओर शिफ्ट करता है। \n
- शुरुआत में खाली हुई कोशिकाओं में नए एलिमेंट लिखता है। \n
unshift push से धीमा क्यों है?
\n\nमेथड push() एलिमेंट को अंत में जोड़ता है — इसे कुछ भी शिफ्ट करने की आवश्यकता नहीं होती। unshift() प्रत्येक मौजूदा एलिमेंट के लिए इंडेक्स को फिर से लिखता है। यदि ऐरे में 1000 एलिमेंट हैं, तो unshift को सभी 1000 को शिफ्ट करना होगा। push बस अंत में जोड़ देता है।
V8 में एक ऑप्टिमाइज़ेशन है: यदि ऐरे खाली या लगभग खाली है, तो शिफ्टिंग लगभग मुफ्त है। लेकिन बड़े ऐरे के लिए प्रदर्शन में अंतर दस गुना हो सकता है। खासकर यदि आप लूप में unshift करते हैं।
// बुरा: लगातार शिफ्टिंग के कारण O(n²)\nlet arr = [];\nfor (let i = 0; i < 10000; i++) {\n arr.unshift(i);\n}\n\n// अच्छा: O(n) — अंत में जोड़ें, फिर रिवर्स करें\nlet arr2 = [];\nfor (let i = 0; i < 10000; i++) {\n arr2.push(i);\n}\narr2.reverse();\n\nविकल्प: spread-ऑपरेटर (ES6+)
\n\nएक आधुनिक और सुरुचिपूर्ण तरीका नया ऐरे बनाने के लिए spread-ऑपरेटर ... का उपयोग करना है:
let oldArray = [2, 3, 4];\nlet newArray = [1, ...oldArray];\nconsole.log(newArray); // [1, 2, 3, 4]\n\nयह दृष्टिकोण मूल ऐरे को म्यूटेट नहीं करता, जो अक्सर फंक्शनल प्रोग्रामिंग (React, Redux) में सुविधाजनक होता है। लेकिन याद रखें: एक नया ऐरे बनता है, और पुराने एलिमेंट कॉपी होते हैं। विशाल ऐरे के लिए यह मेमोरी के हिसाब से महंगा हो सकता है।
\n\nशुरुआत में कई एलिमेंट जोड़ना
\n\nlet base =