गार्बेज कलेक्टेड भाषाओं में लीक का मुख्य कारण अवांछित रेफरेंस हैं। मेमोरी लीक को समझने के लिए, आइए देखें कि मेमोरी फ्रीिंग (गार्बेज कलेक्शन) कैसे काम करती है।
मार्क-एंड-स्वीप एल्गोरिदम - यह एल्गोरिदम "एक ऑब्जेक्ट की अब आवश्यकता नहीं है" की परिभाषा को "एक ऑब्जेक्ट अनरीचेबल है" तक कम कर देता है। यह एल्गोरिदम ऑब्जेक्ट्स के एक सेट के ज्ञान को मानता है जिन्हें रूट्स कहा जाता है। JavaScript में, रूट ग्लोबल ऑब्जेक्ट है। समय-समय पर, GC इन रूट्स से शुरू होता है, इन रूट्स से रेफरेंस किए गए सभी ऑब्जेक्ट्स को रिकर्सिवली ढूंढता है। रूट्स से शुरू करके, GC इस प्रकार सभी रीचेबल ऑब्जेक्ट्स को ढूंढ लेगा और सभी नॉन-रीचेबल ऑब्जेक्ट्स को कलेक्ट करेगा।
मेमोरी लीक के प्रकार
1. ग्लोबल वेरिएबल्स (अनडिक्लेयर्ड/आकस्मिक)
JS में, आप गलती से किसी वेरिएबल को ग्लोबली डिक्लेयर कर सकते हैं यदि आप डिक्लेरेशन कीवर्ड (let, var, const) निर्दिष्ट नहीं करते। JS स्कोप से बाहर निकलते हुए ग्लोबल स्कोप तक पहुंचता है और यदि यह किसी भी स्कोप में वेरिएबल नहीं ढूंढता, तो यह एक ग्लोबल वेरिएबल बनाता है।
उदाहरण
function test() { a = [1, 2, 3] } test() // a को बिना कीवर्ड के इनिशियलाइज़ किया गया और अब यह ग्लोबल स्कोप में है। console.log(a)
आउटपुट
[1, 2, 3]
यह व्यवहार मेमोरी लीक का कारण बन सकता है क्योंकि वेरिएबल्स अनजाने में ग्लोबल स्कोप में मौजूद होते हैं और प्रोग्राम समाप्त होने तक मुक्त नहीं होंगे। इसे डिक्लेरेशन कीवर्ड का उपयोग करके ठीक किया जा सकता है।
2. क्लोजर्स
क्लोजर में मेमोरी लीक तब होती है जब कोई वेरिएबल बाहरी फ़ंक्शन में घोषित होता है और यह नेस्टेड इनर फ़ंक्शन के लिए स्वचालित रूप से उपलब्ध हो जाता है और मेमोरी में बना रहता है भले ही इसका उपयोग नेस्टेड फ़ंक्शन में नहीं किया जा रहा हो/रेफरेंस नहीं किया जा रहा हो।
3. डिटैच्ड DOM/आउट ऑफ DOM रेफरेंस
DOM एक डबली-लिंक्ड ट्री है, ट्री में किसी भी नोड का रेफरेंस होने से पूरा ट्री गार्बेज कलेक्शन से बच जाएगा। डिटैच्ड DOM या आउट ऑफ DOM रेफरेंस का अर्थ है कि नोड्स जिन्हें DOM से हटा दिया गया है लेकिन JS के माध्यम से मेमोरी में हैं। इसका मतलब है कि जब तक कहीं भी किसी वेरिएबल या ऑब्जेक्ट का रेफरेंस है, वह ऑब्जेक्ट DOM से हटाए जाने के बाद भी गार्बेज कलेक्ट नहीं होता। DOM के किसी भाग के साथ काम पूरा होने के बाद JS से रेफरेंस हमेशा हटाएं।
4. इवेंट लिसनर्स
addEventListener() मेथड किसी एलिमेंट से इवेंट हैंडलर अटैच करता है और एक ही एलिमेंट में कई इवेंट हैंडलर्स जोड़े जा सकते हैं। यदि किसी DOM एलिमेंट और उसके इवेंट लिसनर का लाइफसाइकल समान नहीं है, तो यह मेमोरी लीक का कारण बन सकता है।