वेब पर विरोधाभासी जानकारी का एक बहुत कुछ है, इस विषय के बारे में closures। @ जॉन के लिए धन्यवाद, मैं यह काम करने में कामयाब रहा कि बंद (जैसा कि नीचे उपयोग किया गया है) स्मृति रिसाव का कारण नहीं है, और यह भी आईई 8 में- वे लोग आम तौर पर दावा नहीं करते हैं। असल में मेरे कोड में केवल 1 रिसाव हुआ था, जो साबित करना मुश्किल नहीं था।
अब से, इस सवाल का मेरा उत्तर होगा:
AFAIK, केवल समय IE8 लीक, जब घटनाओं से जुड़े होते हैं/संचालकों वैश्विक वस्तु पर सेट कर रहे हैं है। (window.onload
, window.onbeforeunload
, ...)। इसके चारों ओर जाने के लिए, नीचे मेरा जवाब देखें।
विशाल अद्यतन:
मैं पूरी तरह से अब खो रहा हूँ ... कुछ समय के लेख और tuts पुरानी और नई दोनों के माध्यम से खुदाई के बाद, मैं के साथ कम से कम एक humongous छोड़ रहा हूँ अंतर्विरोध। जबकि में से एक जावास्क्रिप्ट गुरु की (डगलस Crockford) का कहना है:
के बाद से आईई अपना काम करने और चक्र को पुनः प्राप्त करने में असमर्थ है, यह हम पर गिर जाता है यह करने के लिए। यदि हम स्पष्ट रूप से चक्र तोड़ते हैं, तो IE स्मृति को पुनः प्राप्त करने में सक्षम होगा। माइक्रोसॉफ्ट के अनुसार, बंद स्मृति मेमोरी लीक का कारण हैं। यह निश्चित रूप से गहराई से गलत है, लेकिन यह माइक्रोसॉफ्ट की ओर जाता है कि माइक्रोसॉफ्ट की बग से निपटने के तरीके पर प्रोग्रामर को बहुत बुरी सलाह दी जाती है। यह पता चला है कि डीओएम पक्ष पर चक्र तोड़ना आसान है। जेस्क्रिप्ट पक्ष पर उन्हें तोड़ना लगभग असंभव है।
और @freakish ने बताया कि नीचे दिए गए मेरे स्निपेट jQuery की आंतरिक कार्यप्रणाली के समान हैं, मुझे अपने समाधान के बारे में बहुत सुरक्षित महसूस हुआ है जिससे स्मृति रिसाव नहीं हो रहा है। उसी समय मुझे this MSDN page मिला, जहां सेक्शन Circular References with Closures
मेरे लिए विशेष रुचि थी। नीचे दिए गए चित्र काफी कैसे मेरे कोड काम करता है की एक योजनाबद्ध प्रतिनिधित्व है, यह नहीं है:
फर्क सिर्फ इतना किया जा रहा है मैं तत्वों खुद को मेरी घटना श्रोताओं संलग्न नहीं की सामान्य ज्ञान है।
सभी एक ही डौगी काफी स्पष्ट है: बंद आईई में मेम-लीक का स्रोत नहीं है। यह विरोधाभास मुझे स्पष्ट करता है कि कौन सही है।
मुझे यह भी पता चला है कि रिसाव मुद्दा IE9 में पूरी तरह से हल नहीं किया गया है (लिंक एटीएम नहीं मिल सकता है)।
एक आखिरी बात: मैं भी जानने के लिए कि IE JScript इंजन के बाहर डोम, जो मुझे परेशान जब मैं एक <select>
तत्व के बच्चों, एक ajax अनुरोध के आधार पर बदलने का एक स्थान में डालता प्रबंधन करता आए हैं :
function changeSeason(e)
{
var xhr,sendVal,targetID;
e = e || window.event;//(IE...
targetID = this.id.replace(/commonSourceFragment/,'commonTargetFragment');//fooHomeSelect -> barHomeSelect
sendVal = this.options[this.selectedIndex].innerHTML.trim().substring(0,1);
xhr = prepareAjax(false,(function(t)
{
return function()
{
reusableCallback.apply(this,[t]);
}
})(document.getElementById(targetID)),'/index/ajax');
xhr({data:{newSelect:sendVal}});
}
function reusableCallback(elem)
{
if (this.readyState === 4 && this.status === 200)
{
var data = JSON.parse(this.responseText);
elem.innerHTML = '<option>' + data.theArray.join('</option><option>') + '</option>';
}
}
आईई वास्तव में डोम का प्रबंधन करता है जैसे कि JScript इंजन वहाँ नहीं थे, बाधाओं कि विकल्प तत्वों इस कोड का उपयोग पुनः आवंटित की जाती नहीं कर रहे हैं क्या हैं?
मैंने जानबूझकर इस स्निपेट को एक उदाहरण के रूप में जोड़ा है, क्योंकि इस मामले में मैं वैरिएबल को पास कर रहा हूं जो वैश्विक कार्य के लिए तर्क के रूप में क्लोजर स्कोप का हिस्सा हैं।मुझे इस अभ्यास पर कोई दस्तावेज नहीं मिला, लेकिन माइक्रोसॉफ्ट द्वारा प्रदान किए गए दस्तावेज के आधार पर, इसे किसी भी परिपत्र संदर्भ को तोड़ना चाहिए, है ना?
चेतावनी: लंबा सवाल ... (खेद)
मैं अजाक्स मेरी वेब अनुप्रयोग में कॉल करने के लिए काफी बड़ी JavaScripts की एक जोड़ी लिखा है। कई कॉलबैक और घटनाओं से बचने के लिए, मैं इवेंट प्रतिनिधिमंडल और बंदियों का पूरा फायदा उठा रहा हूं। अब मैंने एक ऐसा फ़ंक्शन लिखा है जिसमें मुझे संभावित मेमोरी लीक के रूप में सोच रहा है। हालांकि मुझे आईई> 8 सौदों को बंद करने के साथ 8 सौदों को बेहतर माना जाता है, फिर भी इसके पूर्ववर्ती, यह आईई 8 का समर्थन करने के लिए कंपनी नीति है।
नीचे मैंने जो कुछ भी किया है, उसका उदाहरण दिया है, here आप एक समान उदाहरण पा सकते हैं, हालांकि यह AJAX का उपयोग नहीं करता है, लेकिन एक सेटटाइमआउट, परिणाम काफी समान है। onreadystatechange
कॉलबैक के अलावा
function prepareAjax(callback,method,url)
{
method = method || 'POST';
callback = callback || success;//a default CB, just logs/alerts the response
url = url || getUrl();//makes default url /currentController/ajax
var xhr = createXHRObject();//try{}catch etc...
xhr.open(method,url,true);
xhr.setRequestMethod('X-Requested-with','XMLHttpRequest');
xhr.setRequestHeader('Content-type','application/x-www-form-urlencoded');
xhr.setRequestHeader('Accept','*/*');
xhr.onreadystatechange = function()
{
callback.apply(xhr);
}
return function(data)
{
//do some checks on data before sending: data.hasOwnProperty('user') etc...
xhr.send(data);
}
}
सभी सुंदर सीधी-सपाट सामान,: (आप निश्चित रूप से नीचे दिए गए कोड को छोड़ सकते हैं सवाल ही,)
कोड मैं मन में है यह है। मैंने आईई के साथ कुछ मुद्दों को देखा जब सीधे हैंडलर बाध्यकारी: xhr.onreadystatechange = callback;
, इसलिए अनाम कार्य। पता नहीं क्यों, लेकिन मैंने इसे काम करने का सबसे आसान तरीका पाया।
जैसा कि मैंने कहा, मैं कई कार्यक्रम प्रतिनिधिमंडल का उपयोग कर रहा हूं, इसलिए आप कल्पना कर सकते हैं कि यह वास्तविक तत्व/घटना तक पहुंचने के लिए उपयोगी साबित हो सकता है जो अजाक्स कॉल को निकाल देता है।
function handleClick(e)
{
var target,parent,data,i;
e = e || window.event;
target = e.target || e.srcElement;
if (target.tagName.toLowerCase() !== 'input' && target.className !== 'delegateMe')
{
return true;
}
parent = target;
while(parent.tagName.toLowerCase() !== 'tr')
{
parent = parent.parentNode;
}
data = {};
for(i=0;i<parent.cells;i++)
{
data[parent.cells[i].className] = parent.cells[i].innerHTML;
}
//data looks something like {name:'Bar',firstName:'Foo',title:'Mr.'}
i = prepareAjax((function(t)
{
return function()
{
if (this.readyState === 4 && this.status === 200)
{
//check responseText and, if ok:
t.setAttribute('disabled','disabled');
}
}
})(target));
i(data);
}
आप देख सकते हैं, onreadystatechange
कॉलबैक एक समारोह, कि target
तत्व के संदर्भ में जब कॉलबैक कहा जाता है प्रदान करता है के रिटर्न मान है: तो मैं कुछ ईवेंट हैंडलर्स कि इस तरह दिखना है। घटना प्रतिनिधिमंडल के लिए धन्यवाद, मुझे उन घटनाओं के बारे में चिंता करने की ज़रूरत नहीं है जो उस तत्व से बंधे रहें, जब मैं इसे डीओएम से हटाने का फैसला करता हूं (जिसे मैं कभी-कभी करता हूं)।
मेरे मन के लिए, तथापि, कॉलबैक फ़ंक्शन का कॉल वस्तु बहुत ज्यादा IE के JScript इंजन और उसके कचरा कलेक्टर के लिए साबित हो सकता:
घटना ==> हैंडलर ==> prepareAjax एक बहुत साधारण कॉल अनुक्रम है, लेकिन कॉलबैक तर्क:
[anon। func (तर्क टी = लक्ष्य) एनन लौटाता है। एफ prepareAjax करने के लिए एक निजी चर बारी में,]
===> एक anon कॉलबैक फ़ंक्शन पर पारित किया है, XHR वस्तु के लिए विधि .apply का उपयोग कर कहा जाता है (जो बारी refs में वापस लक्षित करने के लिए टी की पहुंच है) फ़ंक्शन
मैंने एफएफ और क्रोम में इस "निर्माण" का परीक्षण किया है। यह ठीक काम करता है, लेकिन बंद होने पर बंद होने पर बंद होने का इस तरह का कॉलस्टैक, प्रत्येक अवसर पर डीओएम तत्व के संदर्भ में गुजरने वाले प्रत्येक अवसर पर IE (विशेष रूप से IE9 से पहले संस्करण) में कोई समस्या हो सकती है?
नहीं, मैं jQuery या अन्य libs का उपयोग नहीं कर रहा हूं। मुझे शुद्ध जेएस पसंद है, और मैं इस गंभीर रूप से अंतर्निहित भाषा के बारे में जितना चाहूं उतना जानना चाहता हूं।कोड स्निपेट वास्तविक प्रति-पेस्ट उदाहरण नहीं हैं, लेकिन आईएमओ प्रदान करते हैं, मैं एक अच्छी प्रतिनिधित्व करता हूं कि मैं अपनी स्क्रिप्ट में प्रतिनिधिमंडल, बंद और कॉलबैक का उपयोग कैसे कर रहा हूं। तो अगर कुछ वाक्यविन्यास बिल्कुल सही नहीं है, तो इसे सही करने के लिए स्वतंत्र महसूस करें, लेकिन यह सवाल यह नहीं है कि यह सवाल निश्चित रूप से है।
मैं क्यों 'xhr.onreadystatechange = callback' आप के लिए काम नहीं करता है पता नहीं है: मामले में किसी को परवाह नहीं है, यहाँ ucFirst स्ट्रिंग विधि है। दिलचस्प। लेकिन वास्तव में इस हिस्से को कोई फर्क नहीं पड़ता, स्मृति रिसाव सबसे दिलचस्प बात है। मैंने कभी ऐसा व्यवहार नहीं देखा है, हालांकि मैंने थोड़ी देर के लिए IE <9 के साथ काम नहीं किया है। – freakish
बीटीडब्ल्यू: आपको jQuery का उपयोग करने की आवश्यकता नहीं है, लेकिन आप इसके स्रोत कोड को देख सकते हैं। :) मैंने किया और ऐसा लगता है कि वे कुछ अलग नहीं कर रहे हैं तो आप हैं। यह स्मृति रिसाव नहीं देना चाहिए। क्या आप निश्चित हैं कि आप कहीं भी 'xhr' का संदर्भ नहीं रखते हैं? या 'तैयार AJAX' परिणाम के लिए? – freakish
@freakish: मुझे उम्मीद नहीं है कि 'xhr.onreadystatechange = callback' स्मृति समस्याओं (यदि कोई हो) का कारण हो। मैंने इसका उल्लेख किया क्योंकि मैं भी, आईई के हिस्से पर यह अजीब व्यवहार पाता हूं। लेकिन मैंने लंबे समय से आईई की तार्किक व्यवहार की आशा छोड़ दी है। आपके अनुसार, क्या यह कोड स्मृति समस्याओं का कारण बन सकता है, यही वह है जो मुझे –