2012-04-10 11 views
10

बनाम कच्चे expando गुण (मनमाने ढंग से गुण आप डोम नोड्स को असाइन कर सकते) jQuery.data का माना लाभों में से एक की सटीक व्याख्या यह है कि jQuery.data "मेमोरी लीक से वृत्तीय संदर्भ से सुरक्षित है और इसलिए मुक्त" है।जावास्क्रिप्ट <-> डोम वृत्तीय संदर्भ मुद्दा

वेब अनुप्रयोगों के लिए सबसे आम मेमोरी लीक जावास्क्रिप्ट स्क्रिप्ट इंजन और ब्राउज़रों 'सी ++ वस्तुओं' जावास्क्रिप्ट के बीच लागू करने डोम (जैसे के बीच परिपत्र संदर्भ शामिल: गूगल से एक लेख "Optimizing JavaScript code" शीर्षक से अधिक विस्तार में चला जाता है स्क्रिप्ट इंजन और इंटरनेट एक्सप्लोरर के COM बुनियादी ढांचे, या जावास्क्रिप्ट इंजन और फ़ायरफ़ॉक्स XPCOM आधारभूत संरचना के बीच)। के माध्यम से expando → मध्यस्थ वस्तु → DOM एलीमेंट

  • DOM एलीमेंट → ईवेंट हैंडलर → बंद गुंजाइश → डोम

  • DOM एलीमेंट →:

यह वृत्तीय संदर्भ पैटर्न के दो उदाहरणों को सूचीबद्ध

हालांकि, यदि एक डोम नोड और जावास्क्रिप्ट ऑब्जेक्ट के बीच एक संदर्भ चक्र स्मृति रिसाव उत्पन्न करता है, तो इसका मतलब यह नहीं है कि कोई भी गैर-मामूली घटना हैंडलर (उदा। onclick) ऐसे रिसाव का उत्पादन करेगा? मुझे नहीं कि यह कैसे भी संभव है एक ईवेंट हैंडलर एक संदर्भ चक्र से बचने के लिए के लिए है, क्योंकि जिस तरह से मैं इसे देख:

  • डोम तत्व का संदर्भ ईवेंट हैंडलर।

  • ईवेंट हैंडलर डीओएम (या तो प्रत्यक्ष या परोक्ष रूप से) का संदर्भ देता है। किसी भी मामले में, window किसी भी रोचक घटना हैंडलर में setInterval लूप लिखने से कम, जो वैश्विक कतार से क्रियाओं को पढ़ता है, को संदर्भित करना लगभग असंभव है।

किसी जावास्क्रिप्ट ↔ डोम वृत्तीय संदर्भ समस्या का एक सटीक विवरण प्रदान कर सकते हैं? चीजें जिन्हें मैं स्पष्ट करना चाहता हूं:

  • कौन से ब्राउज़र प्रभावित होते हैं? JQuery स्रोत में एक टिप्पणी विशेष रूप से आईई 6-7 का उल्लेख करती है, लेकिन Google लेख से पता चलता है कि फ़ायरफ़ॉक्स भी प्रभावित है।

  • विस्तारित गुण और ईवेंट हैंडलर मेमोरी लीक से संबंधित किसी भी तरह से अलग हैं? या ये दोनों कोड स्निपेट एक ही तरह की मेमोरी रिसाव के लिए अतिसंवेदनशील हैं?

    // Create an expando that references to its own element. 
    var elem = document.getElementById('foo'); 
    elem.myself = elem; 
    
    // Create an event handler that references its own element. 
    var elem = document.getElementById('foo'); 
    elem.onclick = function() { 
        elem.style.display = 'none'; 
    }; 
    
  • तो एक पेज लीक स्मृति वजह से एक परिपत्र संदर्भ के लिए, करता रिसाव जारी रहती है जब तक पूरे ब्राउज़र आवेदन बंद कर दिया है, या स्मृति मुक्त हो जाता है जब विंडो/टैब बंद कर दिया है?

+1

क्या यह कोड वास्तव में मेमोरी लीक का कारण बनता है? मुझे समझ नहीं आता क्यों। var elem = document.getElementById ('foo'); elem.myself = elem; – CEGRD

उत्तर

5

यह शायद इन कड़ियों में सभी सामग्री पुनरुत्पादित के लायक नहीं है, तो मैं आपको कुछ पढ़ने और other Google search hits पर एक नज़र कर सुझाव देंगे:

javascript, circular references and memory leaks

Do you know what may cause memory leaks in JavaScript?

http://www.ibm.com/developerworks/web/library/wa-memleak/

http://www.ibm.com/developerworks/web/library/wa-sieve/index.html?ca=drs-

http://code.google.com/p/google-web-toolkit/wiki/UnderstandingMemoryLeaks

सबसे खराब मेमोरी लीक जहां लीक स्थायी होते हैं (आप प्रभावित वेब पेज जाने के बाद भी) IE6 में हैं। अन्य लीक आम तौर पर केवल तभी होते हैं जब आप उस विशिष्ट पृष्ठ पर हों और जब आप पृष्ठ छोड़ते हैं तो साफ़ हो जाएं।

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

jQuery का .data() चीजों को और अधिक विश्वसनीय बनाता है क्योंकि आईई के पुराने संस्करणों में गुणों के साथ एक विशेष समस्या थी जो एक डीओएम तत्व में जोड़ा गया था और परिपत्र संदर्भों को ठीक से उन गुणों में डेटा को शामिल नहीं किया था और इस प्रकार चीजों को मुक्त नहीं किया जाएगा होना चाहिए (एक रिसाव)। .data() डीओएम तत्व पर केवल एक अतिरिक्त संपत्ति का उपयोग करके इसके आसपास काम करता है जो एक सुरक्षित, गैर-लीकिंग स्ट्रिंग है। वह स्ट्रिंग तब एक जावास्क्रिप्ट ऑब्जेक्ट में एक कुंजी है जिसमें सभी गुण हो सकते हैं जिन्हें आप DOM तत्व से जोड़ना चाहते हैं। चूंकि ये गुण सभी सादे जावास्क्रिप्ट में संग्रहीत हैं, जहां ब्राउज़र में परिपत्र संदर्भ बग नहीं होते हैं, इस तरह से ऐसा करने से लीक नहीं होती है।

यह जानना महत्वपूर्ण है कि अभी भी कुछ परिपत्र संदर्भ हो सकते हैं और यह ठीक है। कार्य-आसपास सर्कुलर संदर्भों को उस स्थान पर स्थानांतरित करना है जहां ब्राउज़र उन्हें उन जगहों पर रखने के बजाय उचित रूप से संभालते हैं जिन्हें ब्राउज़र में बग है।

+0

तो आईई 6-7 विस्तारित गुणों के लिए डीओएम और जेएस के बीच परिपत्र संदर्भ एकत्रित नहीं करता है (जो कि '.data' आसपास काम करता है)। क्या यह इवेंट हैंडलर के लिए उचित रूप से कचरा इकट्ठा करता है? –

+0

@joeyadams - मुझे ऐसा लगता है - यह मेरी समझ है। – jfriend00

संबंधित मुद्दे