2013-02-20 14 views
12

मैं थोड़ी देर के लिए काम कर किया जा रहा है जावास्क्रिप्ट में और आम तौर पर कुछ इस तरह करते हैं कार्यों के गुण है कि या एक गहरी संरचना के भीतर घोषित कर रहे हैं "नाम स्थान"जावास्क्रिप्ट बंद प्रदर्शन

//global scope 
(function ($, lib) { 
    //function scope 1 
    var format = lib.format, // instead of calling lib.format all the time just call format 
    touch = lib.pointer.touch, //instead of calling lib.pointer.touch each time just touch 
    $doc = $(document), 
    log = logger.log; //not console log... 


    $doc.on('app:ready', function() { 
    //function scope 2 
    $doc.on('some:event', function (e) { 
     //function scope 3 
     //use the cached variables 
     log(format('{0} was triggered on the $doc object', e.type); 
    }); 

    $doc.on(touch, function (e) { 
     //function scope 3 
     log(format('this should be {1} and is... {0} ', e.type, touch); 
    }); 
    }); 
}(jQuery, lib)); 

मैं था के मूल्य को कैश करने के लिए कर रही है क्योंकि वह:

  • के रूप में आलसी के रूप में मैं कर रहा हूँ, स्पर्श लेखन और अधिक आकर्षक है कि lib.pointer.touch लेखन, यहाँ तक कि जब कल्पना स्वतः पूर्ण के साथ शक्तिशाली IDEs इस पर मदद कर सकता है लगता है, स्पर्श कम है।
  • एक minimizer एक भी पत्र चर करने के लिए है कि एक निजी चर परिवर्तित कर सकते हैं, तो यह भी मेरे लिए कोई मतलब बनाया (मैं जानता हूँ कि, मुझे पता है, बहुत जल्दी अनुकूलन कभी नहीं, लेकिन यह सुरक्षित मुझे लगता है कि हो रहा है)

इस तरह से लिखा गया सभी कोड मोबाइल उपकरणों और डेस्कटॉप ब्राउज़र पर निष्पादित रूप से निष्पादित प्रतीत होता है, इसलिए यह एक सुरक्षित अभ्यास प्रतीत होता है ("अभ्यास" में, पन इरादा)। लेकिन मैं इस बंद में निर्भर करता है के बाद से, और भीतरी कार्यों संदर्भ में यह घोषित किया गया था मैं सोच रहा था बचाने के लिए एक बंद बनाने के लिए है ...

  • एक समारोह के बाहर संदर्भ से चर (मुक्त चर नहीं का उपयोग करता है, तो) ... बंद करने का संदर्भ अभी भी बचाया गया है? (या यदि ia पेड़ लकड़ी में गिरता है और कोई भी इसे सुनने के लिए नहीं होता है, तो क्या यह अभी भी दुर्घटना की आवाज बनाता है? हे) मुझे पता है कि यह जावास्क्रिप्ट इंजन के बीच भिन्न हो सकता है, क्योंकि ईसीएमए ने कुछ भी नहीं बताया है, अगर इसे सहेजने की आवश्यकता है संदर्भ या नहीं जब बाहर से चर का उपयोग नहीं किया जाता है।

  • यदि उपर्युक्त अभिव्यक्ति सत्य है ... क्या कोड का यह ब्लॉक अधिक कुशल होगा?

    //global scope 
    (function ($, lib) { 
        //function scope 1 
        var format = lib.format, 
        touch = lib.pointer.touch, 
        $doc = $(document), 
        log = console.log; 
    
        $doc.on('app:ready', function() { 
    
        (function ($doc, touch, lib, format) { 
         // since all the variables are provided as arguments in this function 
         // there is no need to save them to the [[scope]] of this function 
         // because they are local to this self invoking function now 
         $doc.on('some:event', function (e) { 
         //function scope 3 
         //use the cached variables 
         log(format('{0} was triggered on the $doc object', e.type); 
         }); 
    
         $doc.on(touch, function (e) { 
         //function scope 3 
         log(format('this should be {1} and is... {0} ', e.type, touch); 
         }); 
        }($doc, touch, lib, format));  
    
        }); 
    
    }(jQuery, lib)); 
    

यह और अधिक कुशल है, क्योंकि यह स्वयं तत्काल प्रेरक फ़ंक्शन करने के लिए उन चर गुजरता है? उस नए फ़ंक्शन को कोड में कोई प्रभाव डालने की लागत, (ऋणात्मक या सकारात्मक) होगी?

  • मैं कैसे अपने जावास्क्रिप्ट लाइब्रेरी की मेमोरी खपत को विश्वसनीय तरीके से माप सकता हूं? मेरे पास 100x छोटे जावास्क्रिप्ट मॉड्यूल हैं जो सभी तत्काल स्वयं invoking कार्यों के अंदर ज्यादातर वैश्विक संदर्भ में लीक करने से चर से बचने के लिए है। इसलिए वे सभी ऊपर उल्लिखित कोड के ब्लॉक के समान मॉड्यूल में लपेटे गए हैं।

  • क्या चर के कैश को कैश करने के लिए इसका बेहतर प्रभाव होगा, भले ही इसका मतलब होगा कि वे कहां उपयोग किए जा रहे हैं, वे चर के घोषणाओं को दोहराना होगा?

  • मुझे लगता है कि वर्तमान स्थानीय संदर्भ में एक चर की तलाश नहीं है, इंजन पहले माता-पिता के दायरे को देखेगा और उस स्तर पर सभी चरों पर पुन: प्रयास करेगा ... प्रति स्तर अधिक चर, बदतर होगा शायद एक चर के लिए प्रदर्शन प्रदर्शन हो।

  • आंतरिक बंद होने से एक अनिर्धारित चर खोजने का प्रयास सबसे महंगा होगा, क्योंकि परिभाषा के अनुसार वैरिएबल वैश्विक दायरे तक मूल दायरे पर पहली बार खोज करेगा, और यह नहीं ढूंढने से इंजन अंततः पहुंच जाएगा वैश्विक दायरा क्या यह सच है? इंजन इस तरह के लुकअप अनुकूलित कर रहे हैं?

अंत में ...मुझे पता है कि मैं अपने कोड को दूसरे उदाहरण के रूप में लागू नहीं करना चाहूंगा क्योंकि यह कोड को पढ़ने के लिए कठिन बना देगा और मैं पहले दृष्टिकोण का उपयोग करके अंतिम आउटपुट के न्यूनतम आकार के साथ थोड़े confortable हूँ। मेरा प्रश्न जिज्ञासा से प्रेरित है और जावास्क्रिप्ट की यह वास्तव में अच्छी सुविधा को थोड़ा बेहतर समझने की कोशिश करने के लिए है।

इस परीक्षण के लिए

तदनुसार ...

http://jsperf.com/closures-js

ऐसा लगता है दूसरा दृष्टिकोण तेज है। लेकिन केवल पागलपन की संख्या को पुन: सक्रिय करते समय ही स्पष्ट होता है ... अभी मेरा कोड पुनरावृत्ति की संख्या नहीं करता है ... लेकिन शायद कोडिंग के मेरे तरीके के कारण अधिक स्मृति का उपभोग कर रहा है ...

अद्यतन: यह मुझे बताया गया है कि यह सवाल बहुत बड़ा है। मुझे खेद है कि छोटे हिस्सों में तोड़ने की कोशिश की जाएगी। जैसा कि मैंने कहा था, यह सवाल ज्यादातर जिज्ञासा से प्रेरित था, प्रदर्शन मोबाइल उपकरणों में भी नगण्य लगता है। आपकी सभी प्रतिक्रियाओं के लिए धन्यवाद।

+0

मेरे पास आपके लिए विस्तृत उत्तर नहीं है, लेकिन मुझे कुछ दिन पहले यह मिला है। http://www.developer.nokia.com/Community/Wiki/JavaScript_Performance_Best_Practices –

+3

यह एक बहुत लंबा सवाल है, आपको इसे विभाजित करना पड़ सकता है। – Bergi

+0

हाँ, शायद बहुत लंबा है, लेकिन यह सब एक ही मुद्दे से संबंधित है। मैं इसे तोड़ने की कोशिश करूंगा या कोड उदाहरणों को कम करने के लिए jsfiddle पर ले जाऊंगा। धन्यवाद –

उत्तर

8

मुझे लगता है कि यह समयपूर्व अनुकूलन है। आप पहले से ही जानते हैं कि प्रदर्शन ज्यादातर मामलों में कोई समस्या नहीं है। कसकर लूप में भी, प्रदर्शन उस खराब को कम नहीं करता है। जावास्क्रिप्ट इंजन को इसे अपने आप अनुकूलित करने दें क्योंकि क्रोम ने बंद होने से अनियंत्रित चर को हटाकर, करना शुरू कर दिया है।

एक महत्वपूर्ण बात यह है कि, अपने कोड को अनावश्यक अनुकूलन के साथ पढ़ने के लिए कठिन न बनाएं। आपका उदाहरण काफी हद तक कोड लेता है, विकास में बाधा डालता है। कुछ मामलों में, हमें कोड को पढ़ने के लिए कठिन बनाना पड़ता है क्योंकि हम जानते हैं कि ऐप का एक विशेष टुकड़ा अधिक मेमोरी/प्रदर्शन गहन है, लेकिन केवल उस बिंदु पर हमें ऐसा करना चाहिए।

आप निम्नलिखित कोड (क्रोम में) करने के लिए एक ब्रेकपाइंट जोड़ते हैं, तो आपको लगता है कि world चर बंद से बाहर अनुकूलित किया गया है देखेंगे, स्कोप चर के तहत 'बंद' नोड पर देखने http://jsfiddle.net/4J6JP/1/

enter image description here

(function(){ 
    var hello = "hello", world="world"; 
    setTimeout(function(){ 
     debugger; 
     console.log(hello); 
    }); 
})() 

ध्यान दें कि यदि आप उस आंतरिक कार्य में एक eval जोड़ते हैं, तो सभी दांव बंद हैं और बंद को अनुकूलित नहीं किया जा सकता है।

+0

धन्यवाद आदमी, इसलिए कम से कम आपके लिए एक निष्कर्ष के रूप में बंद होने के प्रदर्शन की परवाह करने की कोई समझ नहीं है जब तक कि वे वास्तव में कोई मुद्दा सही न हो जाएं? और ब्राउज़र बंद होने का अनुकूलन करने के लिए एक अच्छा काम कर रहे हैं। तो आत्म आविष्कार कार्यों के अंदर 100+ मॉड्यूल होने का कोई मुद्दा सही नहीं होना चाहिए? –

+3

जो भी संख्या में, मुझे नहीं लगता कि परिवर्तन ध्यान देने योग्य है। जब तक आपको कोई समस्या न हो, तब तक पढ़ने के लिए सबसे आसान चीज़ों पर चिपकाएं। यह केवल ध्यान देने योग्य होगा जब आप कोड के उस अनुभाग से निपट रहे हैं जो विशेष रूप से स्मृति या प्रदर्शन गहन है –

0

एक प्रदर्शन लागत है जब कार्यों के दायरे और संदर्भ बनाए जाते हैं, अतिरिक्त बच्चे के दायरे में लागत होती है, हालांकि इस मामले में यह नगण्य है। समय पर जाने वाली वस्तुओं या चरों को झुकाव करना, व्याख्यात्मक दायरे पर चढ़ने और वहां खोज करने से तेज़ होगा। नेस्टिंग कार्यों पर एक अच्छा लेख यहाँ है: http://code.tutsplus.com/tutorials/stop-nesting-functions-but-not-all-of-them--net-22315

मैं एक संदर्भ मिलता है और एक शाब्दिक दायरे के अंदर एक वर मुझे लगता है कि हालांकि एक सावधान रहना चाहिए क्योंकि बाद भी माता-पिता समारोह नष्ट हो जाता है क्या करेंगे को असाइन कर सकें तो एक लौटाया गया फ़ंक्शन या ऑब्जेक्ट इन संदर्भों को "long.lib.format" के लिए शॉर्टेंड "प्रारूप" के साथ एक्सेस करने में सक्षम है क्योंकि उन्हें उसी व्याख्यात्मक दायरे के अंदर घोषित किया गया था, यदि आप संदर्भ का उपयोग नहीं कर रहे हैं तो आपको सभी पथों को नष्ट करने की आवश्यकता होगी वह गुंजाइश यह दुखद है लेकिन इस समय यह मेरी समझ है कि हम इस मामले में "संदर्भ" को "var प्रारूप" में हटा नहीं सकते हैं क्योंकि उसी lib को अन्यत्र संदर्भित किया गया है, इस प्रकार "प्रारूप हटाएं" की अनुमति नहीं है हालांकि आप ऑब्जेक्ट/lib पर सदस्यों को हटा सकते हैं यह संदर्भ। आप संदर्भों को पकड़ने के लिए एक स्थानीय वस्तु को अलग कर सकते हैं और उन्हें हटाए जाने पर उन्हें हटा सकते हैं और फिर उस ऑब्जेक्ट को लेक्सिकल स्कोप या चाइल्ड स्कोप के अन्य सदस्यों को खोए बिना

अद्यतन: हाल ही में यह पता चला है कि जावास्क्रिप्ट में डिलीट का उपयोग करना धीमा हो सकता है, बल्कि सदस्य को असाइन करें {} जब अब उपयोग में नहीं है।

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