2012-03-06 10 views
9

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

+7

क्लोजर- https://developer.mozilla.org/en/JavaScript/Guide/Closures – Pranav

+0

के लिए एक सुंदर ट्यूटोरियल मुझे लगता है कि यह सबसे अच्छा लेख है: http://javascript-reference.info/ जावास्क्रिप्ट-क्लोजर-फॉर-डमीज एचटीएम – Sang

उत्तर

1

कारण आप scoped चर के साथ भीतरी समारोह बनाने की जरूरत वस्तु उन्मुख कैप्सूलीकरण है। यह अनिवार्य रूप से निजी चर है।

चर "बंद हो गए" हैं।

// constructor function 
var myObject = function(message) { 
    // private - scope is function level. It's CLOSED OVER the the inner function (closure). 
    //   not delcared as a JSON property so not visible externally 
    var value = 0; 
    // constructor returns JSON object with public methods 
    // always constructed from the myObject var so it always hands back the same instance 
    // of the public methods 
    return { 
     // nested functions have access to outer function variables. 
     increment: function (inc) { 
      value ++; 
     }, 
     getValue: function() { 
      return value; 
     }, 
     // the inner function even has access to the outer function's args! 
     getMessage: message 
    } 
}; 

वापसी विवरण देखें। यह सार्वजनिक इंटरफ़ेस देता है - कुछ विधियों जिनके पास निजी चर तक पहुंच है क्योंकि वे आंतरिक कार्य में हैं। यह ऑब्जेक्ट उन्मुख encapsulation बनाने के लिए जावाScripts फ़ंक्शन स्कोप्ड चर का उपयोग कर रहा है।

उसके बाद मुझे यह पसंद कर सकते हैं: इस बिंदु पर

var obj = myObject('Hello World'); 
obj.increment(); 
obj.increment(); 
console.log(obj.getValue()); 
console.log(obj.getMessage); 
// should be undefined 
console.log(obj.value); 

नोट उपभोक्ता संरक्षित/समझाया मूल्य या संदेश के लिए उपयोग नहीं है।

अब, यहाँ किकर है - वस्तु परिवर्तनशील है तो फोन करने वाले तरीकों में जोड़ सकते हैं या यहां तक ​​कि तरीकों की जगह। तो, आपको लगता है कि कोई व्यक्ति ऐसी पद्धति जोड़ सकता है जो आंतरिक को उजागर करता है। लेकिन, वे कार्यक्षेत्र के कारण नहीं हो सकते (बंद - वे बंद हो गए हैं)। केवल नेस्टेड फ़ंक्शन में बाहरी फ़ंक्शन के चर के लिए उपयोग होता है। इसलिए, यदि कॉलर आंतरिक वापस करने के लिए एक विधि जोड़ता है, तो उन्हें एक्सेस नहीं मिल सकता है और यह अपरिभाषित होगा।

आउटपुट उपरोक्त कोड:

2 
Hello World 
undefined 

एक तरफ ध्यान दें के रूप में, मैं node.js

यहाँ के साथ जावास्क्रिप्ट चल रहा हूँ मॉड्यूल तर्ज पर एक अच्छा ब्लॉग पोस्ट को बंद उपयोग कर रहा है:

http://www.yuiblog.com/blog/2007/06/12/module-pattern/

0

मुद्दा यह है कि चर साझा किया जाता है के मध्य है दो कार्यों में। यदि आपने आंतरिक फ़ंक्शन में चर घोषित किया है, तो बाहरी फ़ंक्शन इसे एक्सेस नहीं कर पाएगा, इसलिए इसे साझा नहीं किया जाएगा।

+0

इसलिए यदि आंतरिक फ़ंक्शन के चर को माई फ़ंक्शंस वैरिएबल से संदर्भित किया गया है, तो भी अंतिम फ़ंक्शन का चर तब भी मूल्य होगा जब इसे अंतिम बार संशोधित किया गया था? – DevX

+0

हां और नहीं। आप बाहरी फ़ंक्शन से आंतरिक फ़ंक्शन में वेरिएबल्स का उल्लेख नहीं कर सकते हैं, इसलिए आंतरिक चर उनके मान रख रहे हैं। 'चेतावनी (आंतरिक) के साथ सिनेथा का उदाहरण परीक्षण करें।foo) '(=> अपरिभाषित) – Teemu

1

आपने अभी अपने प्रश्न का उत्तर दिया है, आंतरिक कार्य इसके चर की रक्षा करता है। jsFiddle

(function outer(){ 
    var foo = 'bar'; 
    function inner(){ 
     var foo = 'OMG NO!'; 
    } 
    alert(foo);//alerts 'bar' 
})() 
1

FROM MDN CLOSURES

why to use: 

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

when not to use 

यह अनावश्यक रूप से अन्य कार्यों के भीतर काम करता है बनाने के लिए बंद किसी विशेष कार्य के रूप में यह नकारात्मक दोनों प्रसंस्करण गति और स्मृति खपत के मामले में स्क्रिप्ट प्रदर्शन को प्रभावित करेगा के लिए आवश्यक नहीं कर रहे हैं, तो बुद्धिमानी नहीं है।

उदाहरण के लिए, जब कोई नई ऑब्जेक्ट/क्लास बनाते हैं, तो सामान्य रूप से ऑब्जेक्ट कन्स्ट्रक्टर में परिभाषित करने के बजाय ऑब्जेक्ट के प्रोटोटाइप से तरीकों को जोड़ा जाना चाहिए। इसका कारण यह है कि जब भी निर्माता को विधियों को बुलाया जाता है तो उसे फिर से सौंप दिया जाएगा (यानी, प्रत्येक वस्तु निर्माण के लिए)।

0

यदि आपने आंतरिक फ़ंक्शन में चर घोषित किया है, तो आंतरिक फ़ंक्शन पर प्रत्येक कॉल एक नया चर बना देगा: पिछली कॉल द्वारा किए गए कोई भी संशोधन खो गए हैं।

लेकिन यदि चर को बाहरी फ़ंक्शन में घोषित किया गया है तो आंतरिक फ़ंक्शन पर एकाधिक कॉल एक ही चर देखेंगे और एक कॉल को पिछले कॉल के संशोधनों को तब तक देखा जाएगा जब तक कि वे दोनों एक ही संस्करण के लिए स्कॉप्ड नहीं थे बाहरी समारोह

+0

तो आप कहने का मतलब यह है कि, जब भी मैं आंतरिक फ़ंक्शन को बार-बार कॉल करता हूं, इसके अंदर चर, जिसे माँ फ़ंक्शन द्वारा बनाए गए चर से संदर्भित किया जाता है, अभी भी इसे संशोधित किया जाएगा जब इसे पहले कहा जाता था? क्योंकि मेरे दिमाग में क्या है कि, आंतरिक फ़ंक्शन का चर भी आंतरिक फ़ंक्शन को कॉल करने पर, माँ फ़ंक्शन से वैरिएबल का मान लेगा। – DevX

3

हमें एक आंतरिक फ़ंक्शन बनाने की आवश्यकता है ताकि बाहरी फ़ंक्शन रिटर्न के बाद बाहरी फ़ंक्शन में चर के अस्तित्व में कुछ अस्तित्व हो।

एक साधारण समारोह पर विचार करें:

function f() { 
    var x = 0; 
    return ++x; // x=1 
} // Once the function has exited then "x" no longer exists. 

ध्यान दें कि चर "x" केवल "सक्रिय" है (जीवित विद्यमान) जब कार्यक्रम का नियंत्रण की शुरुआत से बहती है "च()" समारोह इसके अंत में। अब

function g() { 
    var x = 0; 
    return function() { 
    // Now "x" will live for as long as this function. 
    return ++x; 
    } 
}; 
var counter = g(); 
counter(); // => 1 
counter(); // => 2 
counter(); // => 3 

जब हम "जी()" कहते हैं हम एक और समारोह मिलता है, और "एक्स" सक्रिय है: लेकिन अगर हम एक आंतरिक समारोह में "x" लगा तो एक्स के रूप में लंबे समय के भीतरी समारोह करता है के रूप में रहते हैं जब तक उस कार्य को एक चर द्वारा संदर्भित किया जाता है।

2

बंद होने का उपयोग क्यों करें?

(function(){ 
    var current_page = 1; 
    function previous_page() { 
     current_page--; 
     // update interface 
    } 
    function next_page() { 
     current_page++; 
     // update interface 
    } 
    // a bit of jQuery, ok? 
    $('#previous').click(previous_page); 
    $('#next').click(next_page); 
})(); 

देखो: हम कोई वैश्विक चर, किसी भी भी नहीं समारोह वैश्विक अंतरिक्ष में परिभाषित किया गया है ... अभी तक, हम के लिए "#previous" और "#next" बटन के क्लिक घटनाओं के लिए एक व्यवहार संलग्न किया है एक पेजिंग सुविधा। बंद किए बिना आप इसे कैसे करेंगे? आप कार्यों के अंदर current_page चर को परिभाषित कैसे करेंगे?

+0

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

0

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

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

तो बंद करने का उद्देश्य क्या है? सभी जटिल चरों को छिपाने के लिए और इस तरह एक स्क्रिप्ट को और अधिक उपयोग करने योग्य बनाने के लिए। यदि आपको स्क्रिप्ट में किसी भी फ़ंक्शन का उपयोग करना चाहते हैं, तो आपको प्रत्येक स्क्रिप्ट में प्रत्येक चर के बारे में चिंता करना पड़ता था, ठीक है कि जल्दी से बहुत मुश्किल हो सकता है। हाँ बंद करो!