TypeScript में मेमोरी और गार्बेज कलेक्टर: पर्दे के पीछे क्या छिपा है?
\n\nकल्पना करें कि आप एक घर बना रहे हैं। आप ईंटें, सीमेंट, सरिया खरीदते हैं — लेकिन अगर आप निर्माण का मलबा नहीं हटाते, तो जल्द ही निर्माण स्थल कूड़े का ढेर बन जाएगा। आपके TypeScript कोड में भी ऐसा ही होता है। आप ऑब्जेक्ट, ऐरे, क्लोज़र बनाते हैं — और अगर समय पर मेमोरी खाली नहीं की गई, तो एप्लिकेशन धीमा होने लगता है, और फिर Out of Memory त्रुटि के साथ क्रैश हो जाता है।
इस लेख में, हम समझेंगे कि TypeScript में मेमोरी प्रबंधन और इसका मुख्य उपकरण — गार्बेज कलेक्टर कैसे काम करता है। आप जानेंगे कि मेमोरी खाली करने के पीछे कौन से तंत्र हैं, मेमोरी लीक से कैसे बचें, और क्यों आपका कोड आपके द्वारा उपयोग बंद करने के बाद भी मेगाबाइट्स 'खा' सकता है।
\n\nचलिए शुरू करते हैं!
\n\nTypeScript मेमोरी का प्रबंधन कैसे करता है? मूल बातें
\n\nएक महत्वपूर्ण बात से शुरू करते हैं: TypeScript कोई अलग भाषा नहीं है, बल्कि JavaScript के ऊपर एक परत है। इसका मतलब है कि TypeScript में मेमोरी और गार्बेज कलेक्टर बिल्कुल JavaScript की तरह काम करते हैं। TypeScript मेमोरी प्रबंधन के लिए कोई नया तंत्र नहीं जोड़ता, लेकिन यह हमें अधिक सुरक्षित कोड लिखने के लिए उपकरण (टाइप, इंटरफ़ेस) देता है।
\n\nJavaScript में मेमोरी दो मुख्य क्षेत्रों में विभाजित होती है:
\n\n- \n
- स्टैक (Stack) — प्रिमिटिव (संख्या, स्ट्रिंग, बूलियन मान) और ऑब्जेक्ट के संदर्भ संग्रहीत करता है। फ़ंक्शन से बाहर निकलने पर स्वचालित रूप से खाली हो जाता है। \n
- हीप (Heap) — ऑब्जेक्ट, ऐरे, फ़ंक्शन संग्रहीत करता है। यहीं पर गार्बेज कलेक्टर काम करता है। \n
जब आप लिखते हैं:
\n\nconst user = { name: 'Alice', age: 30 };\n\nवेरिएबल user स्टैक में संग्रहीत होता है और इसमें हीप में ऑब्जेक्ट का संदर्भ होता है। जब तक संदर्भ है — ऑब्जेक्ट जीवित है। जैसे ही संदर्भ गायब होता है — ऑब्जेक्ट 'कचरा' बन जाता है।
TypeScript में गार्बेज कलेक्टर: यह कैसे काम करता है?
\n\nगार्बेज कलेक्टर (Garbage Collector, GC) एक स्वचालित प्रक्रिया है जो उन ऑब्जेक्ट्स को ढूंढता है जिनका कोई संदर्भ नहीं है, और उनके द्वारा घेरी गई मेमोरी को खाली करता है। आधुनिक इंजन (Chrome में V8, Firefox में SpiderMonkey) जटिल एल्गोरिदम का उपयोग करते हैं, लेकिन आधार मार्क-एंड-स्वीप (Mark-and-Sweep) एल्गोरिदम है।
\n\nयह कैसे काम करता है:
\n\n- \n
- GC 'जड़ों' से शुरू होता है — वैश्विक ऑब्जेक्ट, फ़ंक्शन में स्थानीय वेरिएबल जो निष्पादित हो रहे हैं। \n
- यह जड़ों से सभी संदर्भों के माध्यम से जाता है और प्रत्येक सुलभ ऑब्जेक्ट को चिह्नित करता है। \n
- सभी अचिह्नित ऑब्जेक्ट कचरा माने जाते हैं और हटा दिए जाते हैं। \n
यह सरल लगता है, लेकिन व्यवहार में बारीकियाँ हैं। उदाहरण के लिए, चक्रीय संदर्भ:
\n\nfunction createCycle() {\n const obj1: any = {};\n const obj2: any = {};\n obj1.ref = obj2;\n obj2.ref = obj1;\n return 'done';\n}\n\nपहले ऐसी संरचनाएँ मेमोरी लीक का कारण बनती थीं, लेकिन आधुनिक गार्बेज कलेक्टर चक्रों को अच्छी तरह से संभालते हैं — मुख्य बात यह है कि दोनों ऑब्जेक्ट जड़ों से अप्राप्य हों।
\n\nTypeScript एप्लिकेशन में सामान्य मेमोरी लीक
\n\nस्मार्ट गार्बेज कलेक्टर के साथ भी, आप 'गलतियाँ' कर सकते हैं। यहाँ सबसे सामान्य परिदृश्य हैं जो TypeScript में मेमोरी लीक का कारण बनते हैं:
\n\n1. भूले हुए टाइमर और इवेंट हैंडलर
\n\nसबसे आम कारणों में से एक। आपने किसी इवेंट की सदस्यता ली, लेकिन सदस्यता रद्द करना भूल गए:
\n\nclass TimerComponent {\n private intervalId: number;\n\n start() {\n this.intervalId = window.setInterval(() => {\n console.log('Tick');\n }, 1000);\n }\n\n // stop() कॉल करना भूल गए — टाइमर हमेशा के लिए चलता रहेगा!\n}\n\nसमाधान: हमेशा टाइमर साफ़ करें और dispose या ngOnDestroy (Angular के लिए) विधि में इवेंट से सदस्यता रद्द करें।
2. क्लोज़र जो संदर्भ रखते हैं
\n\nक्लोज़र एक शक्तिशाली उपकरण है, लेकिन वे गलती से बड़े ऑब्जेक्ट को बनाए रख सकते हैं:
\n\nfunction createHeavyClosure() {\n const hugeData = new Array(1000