2010-04-12 8 views
18

मैं जावास्क्रिप्ट बंद पर Crockford की बात सुन रहा था और जानकारी छुपा के लाभ के प्रति आश्वस्त हूँ, लेकिन मैं जब कॉलबैक कार्यों का उपयोग करने के लिए की एक फर्म समझ नहीं है।जावास्क्रिप्ट में बंद/कॉलबैक फ़ंक्शंस के लिए उपयोग के मामले क्या हैं?

यह ज्यादातर एक सच्चे बयान है कि एक व्यक्ति के साथ या कॉलबैक के बिना ही कार्यक्षमता को पूरा कर सकता है।

कोई है जो कोड लिख रहा है के रूप में, क्या heuristics या संकेतों मेरे मन में जब जब कॉलबैक/बंद उपयोग करने के लिए निर्धारित करने रखना चाहिए?

मैं कंबल बयान के लिए नहीं देख रहा हूँ, बल्कि जब कॉलबैक सही विचार कर रहे हैं के लिए व्यावहारिक उदाहरण या अंगूठे का नियम की एक सूची 'क्लोजर अधिक सुरक्षित कोड बनाने'।

Crockford की प्रस्तुति: http://www.yuiblog.com/blog/2010/04/08/video-crockonjs-5/

उत्तर

29

सबसे पहले अनुकरण करने के लिए है:

  • कॉलबैक: एक फ़ंक्शन किसी अन्य फ़ंक्शन के लिए तर्क के रूप में पारित किया जाता है, जिसे आम तौर पर होने वाली घटना के परिणामस्वरूप कहा जाता है।
  • बंद: एक बनाए रखा गुंजाइश। अर्थात। अवधारणा है कि जब आप किसी अन्य समारोह के भीतर एक समारोह की घोषणा, बाहरी समारोह की गुंजाइश भीतरी समारोह के भीतर पहुंचा जा सकता है।

कॉलबैक भी बंद हो सकते हैं, लेकिन हमेशा नहीं होते हैं।

यह एक कॉलबैक है:

someProcess(myCallback); 

function myCallback() { 
    alert('Done...'); 
} 

function someProcess(callback) { 
    // does stuff... 
    // ... 
    callback(); 
} 

एक बंद:

function foo(msg) { 

    function bar() { 
     // I can access foo's scope 
     // (i.e. bar can access everything that foo can access) 
     alert(msg); 
    } 

    return bar; 

} 

foo('hello')(); // alerts "hello" 

बंद का एक सामान्य उपयोग की जानकारी-छुपा है, जो भाषा को कैप्सूलीकरण किसी तरह लाने में सहायक है प्रदान करना है । कार्रवाई में यह देखने के लिए the module pattern पर एक नज़र डालें।

एक अन्य आम उपयोग जब तत्वों को ईवेंट हैंडलर्स बाध्यकारी है। जैसे

var myElements = [ /* DOM Collection */ ]; 

for (var i = 0; i < 100; ++i) { 
    myElements[i].onclick = function() { 
     alert('You clicked on: ' + i); 
    }; 
} 

यह काम नहीं करेगा। जब तक तत्व क्लिक किया जाता है, वैरिएबल i99 है।बनाने के लिए यह काम ठीक से हम i का मूल्य कब्जा करने के लिए एक बंद उपयोग ठंड:

function getHandler(n) { 
    return function() { 
     alert('You clicked on: ' + n); 
    }; 
} 

for (var i = 0; i < 100; ++i) { 
    myElements[i].onclick = getHandler(i); 
} 
+0

काउंटर उदाहरण क्लासिक :) है। – Anshul

5

This writeup from Mozilla may answer why use closures and when

इसके अलावा, see this set of examples (especially "What can be done with Closures?" section that has the following exmples):

  • उदाहरण 1: समारोह के साथ setTimeout संदर्भ
  • उदाहरण 2: वस्तु दृष्टान्त तरीके से संबद्ध कर कार्य
  • उदाहरण 3: रिसाव Encapsulating पैदा कार्यक्षमता

मैं ई लग रहा है कि इस Crockford पता लगाया जा सकता है, लेकिन बंद होने की क्लासिक उपयोग निजी उदाहरण या स्थैतिक चर (जो JavaScipt का अभाव है)

12

मान लीजिए कि आप उपयोग करने के लिए जब आप नए डोम तत्वों को बनाने के एक समारोह है कि आप एक अद्वितीय "आईडी" मान देने के लिए उपयोग कर सकते हैं चाहते हैं । अब, जावा की तरह कुछ में, आप एक आंतरिक निजी काउंटर के साथ एक कक्षा बना सकते हैं, और उसके बाद एक विधि है जो काउंटर को कुछ उपसर्ग स्ट्रिंग में जोड़ती है। खैर, जावास्क्रिप्ट में:

var getId = (function() { 
    var counter = 0; 
    return function() { 
    return "prefix" + counter++; 
    }; 
})(); 

अब चर "getId" एक समारोह है कि एक और समारोह से है बनाया करने के लिए बाध्य है, और इस तरह से यह आमंत्रण के बीच का उपयोग करने के एक लगातार परिवर्तनशील है कि में बनाया जाता है। इसी प्रकार, यदि मैं "getId" कार्यों (जैसे कि, मैं जोड़ सकते हैं DOM तत्व के प्रत्येक प्रकार के लिए एक) के एक परिवार है चाहता था, मैं यह कर सकता है:

var getIdFunc = function(prefix) { 
    var counter = 0; 
    return function() { 
    return prefix + counter++; 
    }; 
}; 
var getId = { 
    'div': getIdFunc('div'), 
    'span': getIdFunc('span'), 
    'dl': getIdFunc('dl'), 
    // ... 
}; 

अब मैं एक नया पाने के लिए getId.div() कॉल कर सकते हैं एक नए <div> के लिए "आईडी" मान। फ़ंक्शन को एक फ़ंक्शन को कॉल करके बनाया गया था जो दो को बंद करने में दिए गए मानों को प्रदान करता है: उपसर्ग स्ट्रिंग (एक तर्क के रूप में पारित) और काउंटर (var बंद होने के दायरे में घोषित)।

एक बार जब आप इसका उपयोग कर लेंगे, तो सुविधा इतनी लचीली और उपयोगी होगी कि आपको इसके बिना किसी पर्यावरण में वापस जाने में दर्द महसूस होगा।

ओह, और यहाँ एक टिप मदद करने के लिए आप बंद StackOverflow रखने तो आप इस बाहर की कोशिश करनी चाहिए है:

for (var i = 0; i < 10; ++i) { 
    var id = "foo" + i; 
    var element = document.getElementById(id); 
    element.onclick = function() { 
    alert("hello from element " + i); 
    }; 
} 

क्या समस्या यहाँ है: यह एक ऐसा मुद्दा है हर समय पॉप अप होता है? खैर, वह "i" वैरिएबल जिसे उस फ़ंक्शन द्वारा संदर्भित किया गया है वह उस क्षेत्र से "i" है जिसमें लूप चलता है। वह चर, आप ध्यान देंगे, लूप के माध्यम से वृद्धि हुई है (duhh, सही?)। खैर, इवेंट हैंडलर के रूप में बनाए गए और असाइन किए गए उन छोटे कार्यों में से प्रत्येक एक साझा करेगा, जो क्लोजर स्कोप में एक ही चर, "i" होगा। ऊप्स! समाधान इस तरह कुछ करने के लिए है:

for (var i = 0; i < 10; ++i) { 
    var id = "foo" + i; 
    var element = document.getElementById(id); 
    element.onclick = (function(iCopy) { 
    return function() { 
     alert("hello from element " + iCopy); 
    }; 
    })(i); 
} 

हम की एक प्रतिलिपि बनाने बाहरी "i" अपने आप में एक बंद दायरे में है, इसलिए अब प्रत्येक ईवेंट हैंडलर अपनी ही है!

संक्षेप में: लीवरेजिंग बंद करने की तकनीक सभी फ्रेकिंग समय आती है जब आप इसका उपयोग करते हैं। यह त्रुटि मुक्त प्रोग्रामिंग की एक नई वंडरलैंड में एक मुफ्त टिकट नहीं है; मुझे गलत मत समझो। हालांकि, यह एक बहुत उपयोगी और लचीला प्रतिमान है।

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