javascript उपयोगकर्ता - जावास्क्रिप्ट कैसे काम बंद कर देता है?




खोज की (25)

बच्चे हमेशा अपने माता-पिता के साथ साझा किए गए रहस्यों को याद रखेंगे, यहां तक ​​कि उनके माता-पिता के जाने के बाद भी। कार्यों के लिए यह बंद है।

जावास्क्रिप्ट कार्यों के लिए रहस्य निजी चर हैं

var parent = function() {
 var name = "Mary"; // secret
}

हर बार जब आप इसे कॉल करते हैं, स्थानीय चर "नाम" बनाया जाता है और नाम "मैरी" दिया जाता है। और जब भी फ़ंक्शन से बाहर निकलता है वैरिएबल खो जाता है और नाम भूल जाता है।

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

लेकिन, जावास्क्रिप्ट में यह बहुत ही खास चीज है जो अन्य कार्यों के भीतर बनाई गई फ़ंक्शंस को भी अपने माता-पिता के स्थानीय चरों को जान सकती है और जब तक वे रहते हैं तब तक उन्हें रख सकते हैं।

var parent = function() {
  var name = "Mary";
  var child = function(childName) {
    // I can also see that "name" is "Mary"
  }
}

इसलिए, जब तक हम अभिभावक-कार्य में हैं, तब तक यह एक या अधिक बाल कार्य कर सकता है जो गुप्त स्थान से गुप्त चर साझा करते हैं।

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

तो जीने के लिए, बच्चे को बहुत देर हो चुकी है इससे पहले छोड़ना है

var parent = function() {
  var name = "Mary";
  var child = function(childName) {
    return "My name is " + childName  +", child of " + name; 
  }
  return child; // child leaves the parent ->
}
var child = parent(); // < - and here it is outside 

और अब, हालांकि मैरी "अब नहीं चल रही है", उसकी यादें खो नहीं गई हैं और उसका बच्चा हमेशा उनके नाम और अन्य रहस्यों को याद रखेगा जो उन्होंने अपने समय के दौरान साझा किए थे।

इसलिए, अगर आप बच्चे को "एलिस" कहते हैं, तो वह जवाब देगी

child("Alice") => "My name is Alice, child of Mary"

यह बताने के लिए सब कुछ है।

आप उन अवधारणाओं के ज्ञान के साथ जावास्क्रिप्ट क्लोजर को कैसे समझाएंगे (उदाहरण के लिए फ़ंक्शंस, वेरिएबल्स और जैसे), लेकिन खुद को बंद नहीं करते हैं?

मैंने विकिपीडिया पर दिए गए स्कीम उदाहरण को देखा है, लेकिन दुर्भाग्यवश इससे मदद नहीं मिली।


क्या आप 5 साल की उम्र के बंद होने की व्याख्या कर सकते हैं? *

मुझे अभी भी लगता है कि Google की व्याख्या बहुत अच्छी तरह से काम करती है और संक्षेप में है:

/*
*    When a function is defined in another function and it
*    has access to the outer function's context even after
*    the outer function returns.
*
* An important concept to learn in JavaScript.
*/

function outerFunction(someNum) {
    var someString = 'Hey!';
    var content = document.getElementById('content');
    function innerFunction() {
        content.innerHTML = someNum + ': ' + someString;
        content = null; // Internet Explorer memory leak for DOM reference
    }
    innerFunction();
}

outerFunction(1);​

* एसी # सवाल


स्ट्रॉ मैन

मुझे यह जानने की जरूरत है कि बटन कितनी बार क्लिक किया गया है और प्रत्येक तीसरे क्लिक पर कुछ करें ...

काफी स्पष्ट समाधान

// Declare counter outside event handler's scope
var counter = 0;
var element = document.getElementById('button');

element.addEventListener("click", function() {
  // Increment outside counter
  counter++;

  if (counter === 3) {
    // Do something every third time
    console.log("Third time's the charm!");

    // Reset counter
    counter = 0;
  }
});
<button id="button">Click Me!</button>

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

इस विकल्प पर विचार करें

var element = document.getElementById('button');

element.addEventListener("click", (function() {
  // init the count to 0
  var count = 0;

  return function(e) { // <- This function becomes the click handler
    count++; //    and will retain access to the above `count`

    if (count === 3) {
      // Do something every third time
      console.log("Third time's the charm!");

      //Reset counter
      count = 0;
    }
  };
})());
<button id="button">Click Me!</button>

यहां कुछ चीजें ध्यान दें।

उपर्युक्त उदाहरण में, मैं जावास्क्रिप्ट के बंद व्यवहार का उपयोग कर रहा हूं। यह व्यवहार किसी भी फ़ंक्शन को उस दायरे तक पहुंचने की अनुमति देता है जिसमें इसे बनाया गया था, अनिश्चित काल तक। व्यावहारिक रूप से इसे लागू करने के लिए, मैं तुरंत एक फ़ंक्शन का आह्वान करता हूं जो एक और फ़ंक्शन देता है, और क्योंकि जिस फ़ंक्शन को मैं वापस कर रहा हूं, उसके पास आंतरिक गिनती चर (ऊपर वर्णित बंद व्यवहार के कारण) तक पहुंच है जिसके परिणामस्वरूप परिणामस्वरूप उपयोग के लिए एक निजी दायरा है समारोह ... इतना आसान नहीं है? चलो इसे पतला कर दें ...

एक साधारण एक लाइन बंद

//          _______________________Immediately invoked______________________
//         |                                                                |
//         |        Scope retained for use      ___Returned as the____      |
//         |       only by returned function   |    value of func     |     |
//         |             |            |        |                      |     |
//         v             v            v        v                      v     v
var func = (function() { var a = 'val'; return function() { alert(a); }; })();

लौटाए गए फ़ंक्शन के बाहर सभी चर लौटाए गए फ़ंक्शन पर उपलब्ध हैं, लेकिन वे लौटाए गए फ़ंक्शन ऑब्जेक्ट पर सीधे उपलब्ध नहीं हैं ...

func();  // Alerts "val"
func.a;  // Undefined

उसे ले लो? तो हमारे प्राथमिक उदाहरण में, गिनती चर बंद होने के भीतर निहित है और हमेशा ईवेंट हैंडलर के लिए उपलब्ध है, इसलिए यह क्लिक से क्लिक करने के लिए अपने राज्य को बरकरार रखता है।

साथ ही, यह निजी परिवर्तनीय स्थिति पूरी तरह से सुलभ है, दोनों रीडिंग्स और इसके निजी स्कॉप्ड वेरिएबल्स को असाइन करने के लिए।

तुम वहाँ जाओ; अब आप इस व्यवहार को पूरी तरह से समाहित कर रहे हैं।

पूर्ण ब्लॉग पोस्ट (jQuery विचारों सहित)


जब भी आप किसी अन्य फ़ंक्शन के भीतर फ़ंक्शन कीवर्ड देखते हैं, तो आंतरिक फ़ंक्शन में बाहरी फ़ंक्शन में चर के लिए उपयोग होता है।

function foo(x) {
  var tmp = 3;

  function bar(y) {
    console.log(x + y + (++tmp)); // will log 16
  }

  bar(10);
}

foo(2);

यह हमेशा 16 लॉग करेगा, क्योंकि bar x को एक्सेस कर सकता है जिसे foo लिए तर्क के रूप में परिभाषित किया गया था, और यह foo से tmp तक भी पहुंच सकता है।

यह एक बंद है। एक बंद करने के लिए एक समारोह को वापस करने की आवश्यकता नहीं है। बस अपने तत्काल शब्दावली के दायरे के बाहर चरों तक पहुंचने से एक बंद हो जाता है

function foo(x) {
  var tmp = 3;

  return function (y) {
    console.log(x + y + (++tmp)); // will also log 16
  }
}

var bar = foo(2); // bar is now a closure.
bar(10);

उपर्युक्त फ़ंक्शन 16 लॉग भी करेगा, क्योंकि bar अभी भी x और tmp संदर्भ ले सकता है, भले ही यह अब दायरे के अंदर न हो।

हालांकि, चूंकि tmp अभी भी बंद के बंद होने के आसपास लटक रहा है, इसलिए इसे भी बढ़ाया जा रहा है। जब भी आप bar कॉल करेंगे तो इसे बढ़ाया जाएगा।

बंद करने का सबसे सरल उदाहरण यह है:

var a = 10;

function test() {
  console.log(a); // will output 10
  console.log(b); // will output 6
}
var b = 6;
test();

जब एक जावास्क्रिप्ट फ़ंक्शन लागू किया जाता है, तो एक नया निष्पादन संदर्भ बनाया जाता है। फ़ंक्शन तर्क और पैरेंट ऑब्जेक्ट के साथ, यह निष्पादन संदर्भ इसके बाहर घोषित सभी चर भी प्राप्त करता है (उपरोक्त उदाहरण में, 'ए' और 'बी' दोनों)।

उनमें से एक सूची लौटने या उन्हें वैश्विक चर में सेट करके, एक से अधिक बंद करने का कार्य संभव बनाना संभव है। ये सभी एक ही x और एक ही tmp देखेंगे, वे अपनी प्रतियां नहीं बनाते हैं।

यहां संख्या x एक शाब्दिक संख्या है। जावास्क्रिप्ट में अन्य अक्षरों के साथ, जब foo कहा जाता है, तो संख्या x को foo में इसकी तर्क x रूप में कॉपी किया जाता है।

दूसरी ओर, ऑब्जेक्ट्स से निपटने के दौरान जावास्क्रिप्ट हमेशा संदर्भों का उपयोग करता है। यदि कहें, तो आपने किसी ऑब्जेक्ट के साथ foo कहा है, जो क्लोजर लौटाता है वह उस मूल ऑब्जेक्ट को संदर्भित करेगा!

function foo(x) {
  var tmp = 3;

  return function (y) {
    console.log(x + y + tmp);
    x.memb = x.memb ? x.memb + 1 : 1;
    console.log(x.memb);
  }
}

var age = new Number(2);
var bar = foo(age); // bar is now a closure referencing age.
bar(10);

जैसा कि अपेक्षित है, bar(10) लिए प्रत्येक कॉल x.memb । क्या उम्मीद नहीं की जा सकती है, यह है कि x बस वही वस्तु का जिक्र कर रहा है जैसे age परिवर्तनीय! bar दो कॉल करने के बाद, age.memb 2 होगा! यह संदर्भ HTML ऑब्जेक्ट्स के साथ मेमोरी लीक का आधार है।


मैं इसे छः वर्षीय व्यक्ति को कैसे समझाऊंगा:

आप जानते हैं कि कैसे उगाए गए घर एक घर के मालिक हो सकते हैं, और वे इसे घर कहते हैं? जब एक माँ के बच्चे होते हैं, तो बच्चे का वास्तव में कुछ भी स्वामित्व नहीं होता है, है ना? लेकिन इसके माता-पिता के पास एक घर है, इसलिए जब भी कोई बच्चा "आपका घर कहां है?" पूछता है, तो वह "उस घर" का जवाब दे सकता है, और अपने माता-पिता के घर को इंगित कर सकता है। एक "क्लोजर" हमेशा बच्चे की क्षमता (विदेश में भी) कहने में सक्षम है कि यह घर है, भले ही यह वास्तव में माता-पिता का घर है।


आप सो रहे हैं और आप दान को आमंत्रित करते हैं। आप एक एक्सबॉक्स नियंत्रक लाने के लिए दान बताते हैं।

दान पॉल को आमंत्रित करता है। दान ने पॉल को एक नियंत्रक लाने के लिए कहा। पार्टी में कितने नियंत्रक लाए गए थे?

function sleepOver(howManyControllersToBring) {

    var numberOfDansControllers = howManyControllersToBring;

    return function danInvitedPaul(numberOfPaulsControllers) {
        var totalControllers = numberOfDansControllers + numberOfPaulsControllers;
        return totalControllers;
    }
}

var howManyControllersToBring = 1;

var inviteDan = sleepOver(howManyControllersToBring);

// The only reason Paul was invited is because Dan was invited. 
// So we set Paul's invitation = Dan's invitation.

var danInvitedPaul = inviteDan(howManyControllersToBring);

alert("There were " + danInvitedPaul + " controllers brought to the party.");

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

क्या होगा यदि एक चर का उपयोग किया जाता है, लेकिन यह स्थानीय नहीं है? जैसे यहाँ:

इस मामले में, दुभाषिया बाहरी LexicalEnvironmentवस्तु में परिवर्तनीय पाता है ।

प्रक्रिया में दो कदम होते हैं:

  1. सबसे पहले, जब कोई फ़ंक्शन f बनाया जाता है, तो यह खाली स्थान में नहीं बनाया जाता है। वर्तमान लेक्सिकल एंटरटेनमेंट ऑब्जेक्ट है। उपर्युक्त मामले में, यह खिड़की है (कार्य निर्माण के समय एक अनिर्धारित है)।

जब कोई फ़ंक्शन बनाया जाता है, तो यह एक छिपी हुई संपत्ति हो जाती है, जिसका नाम [[स्कोप]] होता है, जो वर्तमान लेक्सिकल एंटरप्राइज़ का संदर्भ देता है।

यदि एक चर पढ़ा जाता है, लेकिन कहीं भी नहीं पाया जा सकता है, तो एक त्रुटि उत्पन्न होती है।

नेस्टेड फ़ंक्शंस

कार्यों को एक दूसरे के अंदर घोंसला जा सकता है, जो लेक्सिकल वातावरण की एक श्रृंखला बना सकता है जिसे स्कोप चेन भी कहा जा सकता है।

तो, फ़ंक्शन जी में जी, ए और एफ तक पहुंच है।

बंद

बाहरी कार्य समाप्त होने के बाद एक नेस्टेड फ़ंक्शन लाइव रह सकता है:

लेक्सिकल वातावरण को चिह्नित करना:

जैसा कि हम देखते हैं, this.sayउपयोगकर्ता ऑब्जेक्ट में एक संपत्ति है, इसलिए उपयोगकर्ता पूरा होने के बाद यह लाइव रहता है।

और यदि आपको याद है, जब this.sayबनाया जाता है, तो यह (प्रत्येक कार्य के रूप में) this.say.[[Scope]]वर्तमान लेक्सिकल पर्यावरण के लिए आंतरिक संदर्भ प्राप्त करता है। तो, वर्तमान उपयोगकर्ता निष्पादन का लेक्सिकल पर्यावरण पर्यावरण में रहता है। उपयोगकर्ता के सभी चर भी इसकी गुण हैं, इसलिए उन्हें सावधानीपूर्वक रखा जाता है, आमतौर पर जंक नहीं किया जाता है।

पूरा बिंदु यह सुनिश्चित करना है कि यदि आंतरिक कार्य भविष्य में बाहरी चर का उपयोग करना चाहता है, तो ऐसा करने में सक्षम है।

संक्षेप में:

  1. आंतरिक कार्य बाहरी लेक्सिकल पर्यावरण के संदर्भ में रहता है।
  2. बाहरी फ़ंक्शन समाप्त होने के बावजूद आंतरिक फ़ंक्शन किसी भी समय चर से एक्सेस कर सकता है।
  3. ब्राउजर लेक्सिकल एंटरप्राइज और इसकी सभी गुणों (चर) को मेमोरी में तब तक रखता है जब तक कोई आंतरिक फ़ंक्शन न हो।

इसे बंद करना कहा जाता है।


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

क्लोजर सही किया गया:

console.log('CLOSURES DONE RIGHT');

var arr = [];

function createClosure(n) {
    return function () {
        return 'n = ' + n;
    }
}

for (var index = 0; index < 10; index++) {
    arr[index] = createClosure(index);
}

for (var index in arr) {
    console.log(arr[index]());
}
  • उपरोक्त कोड createClosure(n)में लूप के प्रत्येक पुनरावृत्ति में आह्वान किया जाता है। ध्यान दें कि मैं चर नामित nउजागर करने के लिए यह एक है कि नया एक नया कार्य दायरे में बनाया चर और एक ही चर के रूप में नहीं है indexजो बाहरी गुंजाइश के लिए बाध्य है।

  • यह एक नया गुंजाइश बनाता है और nउस दायरे से बंधे हैं; इसका मतलब है कि हमारे पास 10 अलग-अलग स्कोप हैं, प्रत्येक पुनरावृत्ति के लिए एक।

  • createClosure(n) एक ऐसा कार्य देता है जो उस दायरे में एन को वापस कर देता है।

  • प्रत्येक गुंजाइश के भीतर nजो भी मूल्य createClosure(n)लगाया गया था, उसके लिए बाध्य है, इसलिए वापस आने वाले नेस्टेड फ़ंक्शन हमेशा उस मूल्य के मूल्य को वापस कर देंगे nजब createClosure(n)इसे बुलाया गया था।

बंद गलत:

console.log('CLOSURES DONE WRONG');

function createClosureArray() {
    var badArr = [];

    for (var index = 0; index < 10; index++) {
        badArr[index] = function () {
            return 'n = ' + index;
        };
    }
    return badArr;
}

var badArr = createClosureArray();

for (var index in badArr) {
    console.log(badArr[index]());
}
  • उपरोक्त कोड में लूप को createClosureArray()फ़ंक्शन के भीतर ले जाया गया था और फ़ंक्शन अब पूर्ण सरणी लौटाता है, जो पहली नज़र में अधिक सहज लगता है।

  • स्पष्ट नहीं हो सकता है कि चूंकि createClosureArray()केवल लूप के प्रत्येक पुनरावृत्ति के लिए एक के बजाय इस कार्य के लिए केवल एक गुंजाइश बनाई जाती है।

  • इस फ़ंक्शन के भीतर नामित एक चर indexपरिभाषित किया गया है। लूप चलता है और लौटने वाले सरणी में फ़ंक्शंस जोड़ता है index। ध्यान दें कि फ़ंक्शन के indexभीतर परिभाषित किया गया createClosureArrayहै जिसे केवल एक बार ही बुलाया जाता है।

  • क्योंकि createClosureArray()फ़ंक्शन के भीतर केवल एक गुंजाइश थी , indexकेवल उस दायरे के भीतर एक मान के लिए बाध्य है। दूसरे शब्दों में, प्रत्येक बार जब लूप का मान बदलता है index, तो यह उस सब कुछ के लिए बदलता है जो उस दायरे में संदर्भित करता है।

  • सरणी में जोड़े गए सभी फ़ंक्शंस समान indexचर को मूल दायरे से वापस कर देते हैं जहां इसे पहले उदाहरण की तरह 10 अलग-अलग क्षेत्रों से 10 अलग-अलग लोगों के बजाय परिभाषित किया गया था। अंत परिणाम यह है कि सभी 10 कार्य एक ही चर से उसी वैरिएबल को वापस कर देते हैं।

  • लूप समाप्त होने के बाद और indexसंशोधित किया जा रहा था, अंत मूल्य 10 था, इसलिए सरणी में जोड़े गए प्रत्येक फ़ंक्शन एकल indexचर के मान को वापस कर देता है जो अब 10 पर सेट हो जाता है।

परिणाम

क्लोजर सही हो गया
एन = 0
एन = 1
एन = 2
एन = 3
एन = 4
एन = 5
एन = 6
एन = 7
एन = 8
एन = 9

क्लोजर डॉन वांग
एन = 10
एन = 10
एन = 10
एन = 10
एन = 10
एन = 10
एन = 10
एन = 10
एन = 10
एन = 10


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

और हाँ, मैं इसे 6 साल के लिए भी अनुशंसा करता हूं - अगर 6 वर्षीय लोग बंद होने के बारे में सीख रहे हैं, तो यह तार्किक है कि वे लेख में प्रदान की गई संक्षिप्त और सरल व्याख्या को समझने के लिए तैयार हैं ।


बंद सरल हैं:

निम्नलिखित सरल उदाहरण जावास्क्रिप्ट बंद करने के सभी मुख्य बिंदुओं को शामिल करता है। *

यहां एक कारखाना है जो कैलकुलेटर उत्पन्न करता है जो जोड़ और गुणा कर सकता है:

function make_calculator() {
  var n = 0; // this calculator stores a single number n
  return {
    add: function(a) {
      n += a;
      return n;
    },
    multiply: function(a) {
      n *= a;
      return n;
    }
  };
}

first_calculator = make_calculator();
second_calculator = make_calculator();

first_calculator.add(3); // returns 3
second_calculator.add(400); // returns 400

first_calculator.multiply(11); // returns 33
second_calculator.multiply(10); // returns 4000

मुख्य बिंदु: प्रत्येक कॉल make_calculatorएक नया स्थानीय चर बनाने के लिए बनाता है n, जो उस कैलक्यूलेटर द्वारा उपयोग करने योग्य है addऔर रिटर्न के multiplyबाद लंबे समय तक कार्य करता make_calculatorहै।

यदि आप स्टैक फ्रेम से परिचित हैं, तो ये कैलकुलेटर अजीब लगते हैं: वे रिटर्न के nबाद कैसे पहुंच सकते हैं make_calculator? जवाब यह कल्पना करना है कि जावास्क्रिप्ट "स्टैक फ्रेम" का उपयोग नहीं करता है, लेकिन इसके बजाय "हीप फ्रेम" का उपयोग करता है, जो फ़ंक्शन कॉल के बाद जारी रह सकता है जो उन्हें वापस कर देता है।

आंतरिक कार्यों जैसे कि , addऔर multiplyबाहरी फ़ंक्शन ** में घोषित चर का उपयोग करने वाले आंतरिक कार्यों को बंद कर दिया जाता है ।

यह बंद करने के लिए बहुत कुछ है।


* उदाहरण के लिए, यह किसी अन्य उत्तर में दिए गए "क्लोजर्स फॉर डमीज" आलेख में सभी बिंदुओं को शामिल करता है , उदाहरण 6 को छोड़कर, जो आसानी से दिखाता है कि चर घोषित किए जाने से पहले इसका उपयोग किया जा सकता है, जानने के लिए एक अच्छा तथ्य है लेकिन बंद होने से पूरी तरह से असंबंधित है। यह स्वीकार्य उत्तर में सभी बिंदुओं को भी शामिल करता है , अंक (1) को छोड़कर जो उनके तर्कों को स्थानीय चर (नामित फ़ंक्शन तर्क) में कॉपी करते हैं, और (2) जो संख्याओं की प्रतिलिपि बनाना एक नया नंबर बनाता है, लेकिन ऑब्जेक्ट संदर्भ की प्रतिलिपि बनाना आपको एक ही वस्तु का एक और संदर्भ देता है। ये जानने के लिए भी अच्छे हैं लेकिन फिर से बंद करने के लिए पूरी तरह से असंबंधित हैं। यह इस उत्तर में उदाहरण के समान ही है लेकिन थोड़ा छोटा और कम सार है। यह बिंदु को कवर नहीं करता हैयह उत्तर या यह टिप्पणी , जो कि जावास्क्रिप्ट वर्तमान को प्लग करना मुश्किल बनाता हैआपके आंतरिक फ़ंक्शन में लूप वैरिएबल का मान: "प्लग इन" चरण केवल एक सहायक फ़ंक्शन के साथ किया जा सकता है जो आपके आंतरिक फ़ंक्शन को संलग्न करता है और प्रत्येक लूप पुनरावृत्ति पर लगाया जाता है। (कड़ाई से बोलते हुए, आंतरिक फ़ंक्शन वेल्फ़ फ़ंक्शन की प्रतिलिपि को प्रतिलिपि बनाने की बजाय प्रतिलिपि की प्रतिलिपि तक पहुंचता है।) फिर, बंद होने पर बहुत उपयोगी, लेकिन बंद होने का यह हिस्सा नहीं है या यह कैसे काम करता है। एमएल जैसे कार्यात्मक भाषाओं में अलग-अलग काम करने वाले बंद होने के कारण अतिरिक्त भ्रम है, जहां स्टोरेज स्पेस के बजाय वैरिएबल मूल्यों से बंधे होते हैं, जो एक तरह से बंद करने को समझने वाले लोगों की निरंतर धारा प्रदान करते हैं (अर्थात् "प्लग इन" तरीके) जावास्क्रिप्ट के लिए बस गलत है, जहां चर हमेशा भंडारण स्थान से बंधे होते हैं, और कभी भी मूल्यों के लिए नहीं।

** कोई बाहरी कार्य, यदि कई घोंसला हैं, या यहां तक ​​कि वैश्विक संदर्भ में भी, क्योंकि यह उत्तर स्पष्ट रूप से बताता है।


क्लोजर को समझाना मुश्किल होता है क्योंकि उनका उपयोग कुछ व्यवहार करने के लिए किया जाता है कि हर कोई सहजता से काम करने की अपेक्षा करता है। मुझे उन्हें समझाने का सबसे अच्छा तरीका मिल गया है (और जिस तरह से मैंने सीखा है कि वे क्या करते हैं) उनके बिना स्थिति की कल्पना करना है:

    var bind = function(x) {
        return function(y) { return x + y; };
    }
    
    var plus5 = bind(5);
    console.log(plus5(3));

अगर जावास्क्रिप्ट को बंद नहीं पता था तो क्या होगा? बस अपनी विधि निकाय द्वारा अंतिम पंक्ति में कॉल को प्रतिस्थापित करें (जो मूल रूप से फ़ंक्शन कॉल करता है) और आपको मिलता है:

console.log(x + 3);

अब, x की परिभाषा कहां है? हमने इसे मौजूदा दायरे में परिभाषित नहीं किया है। एकमात्र समाधान plus5 को अपने दायरे (या बल्कि, इसके माता-पिता के दायरे) को ले जाने देना है। इस तरह, x अच्छी तरह से परिभाषित है और यह मूल्य 5 के लिए बाध्य है।


फॉरवर्ड: यह जवाब तब लिखा गया था जब प्रश्न था:

पुराने अल्बर्ट की तरह कहा: "यदि आप इसे छह साल के लिए समझा नहीं सकते हैं, तो आप वास्तव में इसे स्वयं नहीं समझते हैं।" ठीक है, मैंने 27 साल के मित्र को जेएस बंद करने की व्याख्या करने की कोशिश की और पूरी तरह असफल रहा।

क्या कोई इस बात पर विचार कर सकता है कि मैं 6 वर्ष का हूं और उस विषय में अजीब दिलचस्पी लेता हूं?

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

मुश्किल अवधारणाओं को समझते समय मैं समानता और रूपक का बड़ा प्रशंसक हूं, इसलिए मुझे एक कहानी के साथ अपना हाथ आज़माएं।

एक ज़माने में:

एक राजकुमारी थी ...

function princess() {

वह रोमांच से भरा एक अद्भुत दुनिया में रहती थी। वह अपने राजकुमार चर्मिंग से मुलाकात की, एक यूनिकॉर्न पर अपनी दुनिया भर में घूमती हुई, ड्रेगन से लड़ने, जानवरों से बात करने का सामना करना पड़ा, और कई अन्य fantastical चीजें।

    var adventures = [];

    function princeCharming() { /* ... */ }

    var unicorn = { /* ... */ },
        dragons = [ /* ... */ ],
        squirrel = "Hello!";

    /* ... */

लेकिन उसे हमेशा कामों और उगाहने की अपनी सुस्त दुनिया में वापस लौटना होगा।

    return {

और वह अक्सर उन्हें राजकुमारी के रूप में अपने नवीनतम अद्भुत साहसिक के बारे में बताती थी।

        story: function() {
            return adventures[adventures.length - 1];
        }
    };
}

लेकिन वे सब एक छोटी लड़की देखेंगे ...

var littleGirl = princess();

... जादू और कल्पना के बारे में कहानियां कह रही है।

littleGirl.story();

और भले ही उगाए जाने वाले लोग असली राजकुमारियों के बारे में जानते थे, फिर भी वे यूनिकोरन्स या ड्रेगन में कभी विश्वास नहीं करेंगे क्योंकि वे उन्हें कभी नहीं देख पाएंगे। उगाए गए लोगों ने कहा कि वे केवल छोटी लड़की की कल्पना के अंदर मौजूद थे।

लेकिन हम असली सच्चाई जानते हैं; कि राजकुमारी के साथ छोटी लड़की अंदर ...

... वास्तव में अंदर एक छोटी लड़की के साथ एक राजकुमारी है।


शुरुआती के लिए जावास्क्रिप्ट बंद

मॉरिस ऑन ट्यू द्वारा प्रस्तुत, 2006-02-21 10:19। तब से समुदाय-संपादित।

बंद जादू नहीं हैं

यह पृष्ठ बंद करने की व्याख्या करता है ताकि एक प्रोग्रामर उन्हें समझ सके - वर्किंग जावास्क्रिप्ट कोड का उपयोग कर। यह गुरु या कार्यात्मक प्रोग्रामर के लिए नहीं है।

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

यह आलेख प्रोग्रामर के लिए मुख्यधारा की भाषा में कुछ प्रोग्रामिंग अनुभव के साथ है, और निम्न जावास्क्रिप्ट फ़ंक्शन को कौन पढ़ सकता है:

function sayHello(name) {
  var text = 'Hello ' + name;
  var say = function() { console.log(text); }
  say();
}
sayHello('Joe');

दो संक्षिप्त सारांश

  • जब कोई फ़ंक्शन (foo) अन्य फ़ंक्शंस (बार और बाज़) घोषित करता है, तो फ़ंक्शन में बनाए गए स्थानीय चर के परिवार को समाप्त होने पर नष्ट नहीं किया जाता है। चर केवल बाहरी दुनिया के लिए अदृश्य हो जाते हैं। इसलिए फू फ़ंक्शन बार और बाज़ को चालाकी से वापस कर सकता है, और वे चर के इस बंद-बंद परिवार ("बंद") के माध्यम से एक-दूसरे के साथ पढ़ना, लिखना और संवाद करना जारी रख सकते हैं, जो कि किसी और के साथ दखल नहीं दे सकता है, यहां तक ​​कि कोई भी जो कॉल नहीं करता भविष्य में फिर से foo।

  • एक बंद करना प्रथम श्रेणी के कार्यों का समर्थन करने का एक तरीका है; यह एक अभिव्यक्ति है जो इसके दायरे के भीतर चर का संदर्भ दे सकती है (जब इसे पहली बार घोषित किया गया था), एक चर को असाइन किया जाना चाहिए, किसी फ़ंक्शन के लिए तर्क के रूप में पारित किया जाना चाहिए, या फ़ंक्शन परिणाम के रूप में वापस किया जाना चाहिए।

बंद करने का एक उदाहरण

निम्न कोड किसी फ़ंक्शन का संदर्भ देता है:

function sayHello2(name) {
  var text = 'Hello ' + name; // Local variable
  var say = function() { console.log(text); }
  return say;
}
var say2 = sayHello2('Bob');
say2(); // logs "Hello Bob"

अधिकांश जावास्क्रिप्ट प्रोग्रामर समझेंगे कि किसी फ़ंक्शन का संदर्भ उपरोक्त कोड में एक चर ( say2 ) पर कैसे लौटाया जाता है। यदि आप नहीं करते हैं, तो बंद करने के बारे में जानने से पहले आपको इसे देखना होगा। सी का उपयोग करने वाला एक प्रोग्रामर फ़ंक्शन को एक फ़ंक्शन पर पॉइंटर लौटने के रूप में सोचता है, और वेरिएबल्स say और say प्रत्येक फ़ंक्शन में पॉइंटर थे।

किसी फ़ंक्शन में सी पॉइंटर और फ़ंक्शन के लिए जावास्क्रिप्ट संदर्भ के बीच एक महत्वपूर्ण अंतर है। जावास्क्रिप्ट में, आप फंक्शन रेफरेंस वैरिएबल के बारे में सोच सकते हैं क्योंकि एक फंक्शन के लिए पॉइंटर और एक बंद करने के लिए एक छिपे हुए पॉइंटर के रूप में।

उपरोक्त कोड में एक बंद है क्योंकि अज्ञात फ़ंक्शन function() { console.log(text); } function() { console.log(text); } को एक और समारोह के अंदर घोषित किया गया है, इस उदाहरण में sayHello2() । जावास्क्रिप्ट में, यदि आप किसी अन्य फ़ंक्शन के अंदर function कीवर्ड का उपयोग करते हैं, तो आप एक बंद कर रहे हैं।

सी और अन्य सामान्य भाषाओं में, फ़ंक्शन रिटर्न के बाद , सभी स्थानीय चर अब उपलब्ध नहीं हैं क्योंकि स्टैक-फ्रेम नष्ट हो जाता है।

जावास्क्रिप्ट में, यदि आप किसी अन्य फ़ंक्शन के भीतर फ़ंक्शन घोषित करते हैं, तो बाहरी फ़ंक्शन के स्थानीय चर इसके से लौटने के बाद पहुंच योग्य रह सकते हैं। यह उपरोक्त प्रदर्शित किया गया है, क्योंकि हम कहने के बाद कहते हैं कि हम कहते हैं कि say2() से वापस आ गया है। ध्यान दें कि जिस कोड को हम कॉल करते हैं वह वेरिएबल text संदर्भ देता है, जो फ़ंक्शन का स्थानीय चर था, sayHello2()

function() { console.log(text); } // Output of say2.toString();

say2.toString() के आउटपुट को देखते हुए, हम देख सकते हैं कि कोड वेरिएबल text को संदर्भित करता है। अज्ञात फ़ंक्शन text को संदर्भित कर सकता है जिसमें 'Hello Bob' मान होता है क्योंकि sayHello2() के स्थानीय चर को sayHello2() को बंद में गुप्त रूप से जिंदा रखा गया है।

प्रतिभा यह है कि जावास्क्रिप्ट में एक फ़ंक्शन संदर्भ में बंद होने वाले बंद होने का एक गुप्त संदर्भ भी होता है - इसी प्रकार प्रतिनिधि एक विधि सूचक और ऑब्जेक्ट का गुप्त संदर्भ कैसे होते हैं।

और ज्यादा उदाहरण

किसी कारण से, जब आप उनके बारे में पढ़ते हैं तो बंद होने में वास्तव में मुश्किल लगती है, लेकिन जब आप कुछ उदाहरण देखते हैं, तो यह स्पष्ट हो जाता है कि वे कैसे काम करते हैं (मुझे थोड़ी देर लग गई)। मैं उदाहरणों के माध्यम से सावधानी से काम करने की सलाह देता हूं जब तक कि आप समझें कि वे कैसे काम करते हैं। यदि आप पूरी तरह से समझने के बिना बंद करने का उपयोग करना शुरू करते हैं, तो आप जल्द ही कुछ अजीब बग बनायेंगे!

उदाहरण 3

यह उदाहरण दिखाता है कि स्थानीय चर की प्रतिलिपि बनाई गई नहीं है - उन्हें संदर्भ द्वारा रखा जाता है। ऐसा लगता है कि बाहरी कार्य मौजूद होने के बावजूद स्टैक-फ्रेम स्मृति में जीवित रहता है!

function say667() {
  // Local variable that ends up within closure
  var num = 42;
  var say = function() { console.log(num); }
  num++;
  return say;
}
var sayNumber = say667();
sayNumber(); // logs 43

उदाहरण 4

सभी तीन वैश्विक कार्यों में एक ही बंद होने का एक आम संदर्भ है क्योंकि वे सभी को setupSomeGlobals() करने के लिए एक ही कॉल के भीतर घोषित किया जाता है।

var gLogNumber, gIncreaseNumber, gSetNumber;
function setupSomeGlobals() {
  // Local variable that ends up within closure
  var num = 42;
  // Store some references to functions as global variables
  gLogNumber = function() { console.log(num); }
  gIncreaseNumber = function() { num++; }
  gSetNumber = function(x) { num = x; }
}

setupSomeGlobals();
gIncreaseNumber();
gLogNumber(); // 43
gSetNumber(5);
gLogNumber(); // 5

var oldLog = gLogNumber;

setupSomeGlobals();
gLogNumber(); // 42

oldLog() // 5

तीन कार्यों को एक ही बंद करने के लिए साझा किया गया है - setupSomeGlobals() के स्थानीय चर setupSomeGlobals() जब तीन कार्यों को परिभाषित किया गया था।

ध्यान दें कि उपर्युक्त उदाहरण में, यदि आप setupSomeGlobals() फिर से कॉल करते हैं, तो एक नया बंद (स्टैक-फ्रेम!) बनाया गया है। पुराना gLogNumber , gIncreaseNumber , gSetNumber चर नए फ़ंक्शन के साथ नए कार्यों के साथ ओवरराइट किए जाते हैं। (जावास्क्रिप्ट में, जब भी आप किसी अन्य फ़ंक्शन के अंदर कोई फ़ंक्शन घोषित करते हैं, तो अंदरूनी फ़ंक्शन प्रत्येक बार बाहरी फ़ंक्शन कहलाता है / फिर से बनाया जाता है।)

उदाहरण 5

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

function sayAlice() {
    var say = function() { console.log(alice); }
    // Local variable that ends up within closure
    var alice = 'Hello Alice';
    return say;
}
sayAlice()();// logs "Hello Alice"

ट्रिकी: यह भी ध्यान रखें कि say चर भी बंद होने के अंदर है, और किसी भी अन्य फ़ंक्शन द्वारा एक्सेस किया जा सकता है जिसे sayAlice() भीतर घोषित किया जा सकता है, या इसे अंदर के फ़ंक्शन के भीतर रिकर्सिव रूप से एक्सेस किया जा सकता है।

उदाहरण 6

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

इस उदाहरण को समझने के लिए आपको जावास्क्रिप्ट में "वेरिएबल होस्टिंग" सुविधा को समझने की आवश्यकता है।

function buildList(list) {
    var result = [];
    for (var i = 0; i < list.length; i++) {
        var item = 'item' + i;
        result.push( function() {console.log(item + ' ' + list[i])} );
    }
    return result;
}

function testList() {
    var fnlist = buildList([1,2,3]);
    // Using j only to help prevent confusion -- could use i.
    for (var j = 0; j < fnlist.length; j++) {
        fnlist[j]();
    }
}

 testList() //logs "item2 undefined" 3 times

लाइन result.push( function() {console.log(item + ' ' + list[i])} परिणाम सरणी में तीन बार अज्ञात फ़ंक्शन का संदर्भ जोड़ता है। यदि आप अज्ञात कार्यों से परिचित नहीं हैं यह ऐसा है:

pointer = function() {console.log(item + ' ' + list[i])};
result.push(pointer);

ध्यान दें कि जब आप उदाहरण चलाते हैं, तो "item2 undefined" तीन बार लॉग होता है! ऐसा इसलिए है क्योंकि पिछले उदाहरणों की तरह, buildList लिए स्थानीय चर के लिए केवल एक बंद है (जिसके result , i और item )। जब अज्ञात फ़ंक्शन लाइन fnlist[j]() पर कॉल किए जाते हैं; वे सभी एक ही बंद होने का उपयोग करते हैं, और वे उस बंद के भीतर i और item लिए वर्तमान मान का उपयोग करते हैं (जहां i पास 3 मान है क्योंकि लूप पूरा हो गया था, और item में 'item2' का मान है)। ध्यान दें कि हम 0 से अनुक्रमणित कर रहे हैं इसलिए item में item का मान है। और i ++ i मूल्य 3

यह देखने में मददगार हो सकता है कि क्या होता है जब भिन्न कीवर्ड के माध्यम से फ़ंक्शन-स्कोप्ड वेरिएबल घोषणा के बजाय वेरिएबल item की ब्लॉक-स्तरीय घोषणा का उपयोग किया जाता है ( let कीवर्ड के माध्यम से)। यदि वह परिवर्तन किया जाता है, तो सरणी result में प्रत्येक अज्ञात फ़ंक्शन का अपना बंद होना होता है; जब उदाहरण चलाया जाता है तो आउटपुट निम्नानुसार होता है:

item0 undefined
item1 undefined
item2 undefined

यदि वेरिएबल i को var बजाय let भी परिभाषित किया गया है, तो आउटपुट है:

item0 1
item1 2
item2 3

उदाहरण 7

इस अंतिम उदाहरण में, मुख्य समारोह में प्रत्येक कॉल एक अलग बंद बनाता है।

function newClosure(someNum, someRef) {
    // Local variables that end up within closure
    var num = someNum;
    var anArray = [1,2,3];
    var ref = someRef;
    return function(x) {
        num += x;
        anArray.push(num);
        console.log('num: ' + num +
            '; anArray: ' + anArray.toString() +
            '; ref.someVar: ' + ref.someVar + ';');
      }
}
obj = {someVar: 4};
fn1 = newClosure(4, obj);
fn2 = newClosure(5, obj);
fn1(1); // num: 5; anArray: 1,2,3,5; ref.someVar: 4;
fn2(1); // num: 6; anArray: 1,2,3,6; ref.someVar: 4;
obj.someVar++;
fn1(2); // num: 7; anArray: 1,2,3,5,7; ref.someVar: 5;
fn2(2); // num: 8; anArray: 1,2,3,6,8; ref.someVar: 5;

सारांश

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

अंतिम अंक:

  • जब भी आप किसी अन्य function अंदर function उपयोग function , तो बंद होने का उपयोग किया जाता है।
  • जब भी आप किसी फ़ंक्शन के अंदर eval() उपयोग करते हैं, तो एक बंद करने का उपयोग किया जाता है। आपके द्वारा eval पाठ फ़ंक्शन के स्थानीय चर का संदर्भ दे सकता है, और eval भीतर आप eval('var foo = …') का उपयोग करके नए स्थानीय चर भी बना सकते हैं।
  • जब आप new Function(…) अंदर new Function(…) ( फंक्शन कन्स्ट्रक्टर ) का उपयोग करते हैं, तो यह बंद नहीं होता है। (नया फ़ंक्शन बाहरी फ़ंक्शन के स्थानीय चर का संदर्भ नहीं दे सकता है।)
  • जावास्क्रिप्ट में एक बंद करना सभी स्थानीय चर की एक प्रति रखने की तरह है, जैसे कि जब कोई फ़ंक्शन निकलता था।
  • शायद यह सोचने के लिए सबसे अच्छा है कि एक बंद हमेशा एक समारोह में प्रवेश किया जाता है, और स्थानीय चर को उस बंद करने के लिए जोड़ा जाता है।
  • स्थानीय चर के एक नए सेट को हर बार एक बंद करने के साथ एक समारोह कहा जाता है (यह देखते हुए कि फ़ंक्शन में इसके अंदर एक फ़ंक्शन घोषणा है, और उस अंदर के फ़ंक्शन का संदर्भ या तो लौटाया गया है या किसी बाहरी तरीके से बाहरी संदर्भ रखा गया है )।
  • दो कार्य ऐसा लग सकते हैं कि उनके पास एक ही स्रोत टेक्स्ट है, लेकिन उनके 'छिपा' बंद होने के कारण पूरी तरह से अलग व्यवहार है। मुझे नहीं लगता कि जावास्क्रिप्ट कोड वास्तव में पता लगा सकता है कि फ़ंक्शन संदर्भ में बंद होना है या नहीं।
  • यदि आप कोई गतिशील स्रोत कोड संशोधन करने की कोशिश कर रहे हैं (उदाहरण के लिए: myFunction = Function(myFunction.toString().replace(/Hello/,'Hola')); ), अगर myFunction एक बंद है तो यह काम नहीं करेगा ( बेशक, आप रनटाइम पर सोर्स कोड स्ट्रिंग प्रतिस्थापन करने के बारे में भी कभी नहीं सोचेंगे, लेकिन ...)।
  • कार्यों और mdash के भीतर फ़ंक्शन घोषणाओं के भीतर फ़ंक्शन घोषणाएं प्राप्त करना संभव है, और आप एक से अधिक स्तर पर बंद हो सकते हैं।
  • मुझे लगता है कि आम तौर पर बंद होने वाले चर के साथ दोनों कार्यों के लिए एक बंद शब्द होता है। ध्यान दें कि मैं इस आलेख में उस परिभाषा का उपयोग नहीं करता!
  • मुझे संदेह है कि जावास्क्रिप्ट में बंद होने वाले सामान्यतः कार्यात्मक भाषाओं में पाए जाते हैं।

लिंक

धन्यवाद

अगर आपने अभी बंद किया है (यहां या कहीं और!), तो मुझे आपके द्वारा सुझाए गए किसी भी बदलाव के बारे में किसी भी प्रतिक्रिया में दिलचस्पी है जो इस लेख को स्पष्ट कर सकता है। Morrisjohns.com (morris_closure @) को एक ईमेल भेजें। कृपया ध्यान दें कि मैं जावास्क्रिप्ट पर गुरु नहीं हूं - न ही बंद होने पर।

मॉरिस द्वारा मूल पोस्ट इंटरनेट आर्काइव में पाया जा सकता है।


बंद पर विकिपीडिया :

कंप्यूटर विज्ञान में, एक क्लोजर एक समारोह है जिसमें उस फ़ंक्शन के नॉनोकोकल नाम (फ्री चर) के लिए एक संदर्भ वातावरण है।

तकनीकी रूप से, JavaScript , प्रत्येक कार्य एक बंद है । यह हमेशा आसपास के दायरे में परिभाषित चर के लिए एक पहुंच है।

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

क्लोजर का उपयोग अक्सर कुछ छिपे हुए निजी डेटा के साथ कार्यों को बनाने के लिए किया जाता है (लेकिन यह हमेशा मामला नहीं है)।

var db = (function() {
    // Create a hidden object, which will hold the data
    // it's inaccessible from the outside.
    var data = {};

    // Make a function, which will provide some access to the data.
    return function(key, val) {
        if (val === undefined) { return data[key] } // Get
        else { return data[key] = val } // Set
    }
    // We are calling the anonymous surrounding function,
    // returning the above inner function, which is a closure.
})();

db('x')    // -> undefined
db('x', 1) // Set x to 1
db('x')    // -> 1
// It's impossible to access the data object itself.
// We are able to get or set individual it.

ईएमएस

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


मैंने एक इंटरैक्टिव जावास्क्रिप्ट ट्यूटोरियल एक साथ रखा है ताकि यह बताने के लिए कि कैसे काम बंद हो जाता है। बंद क्या है?

यहां उदाहरणों में से एक है:

var create = function (x) {
    var f = function () {
        return x; // We can refer to x here!
    };
    return f;
};
// 'create' takes one argument, creates a function

var g = create(42);
// g is a function that takes no arguments now

var y = g();
// y is 42 here

जावास्क्रिप्ट में एक फ़ंक्शन केवल निर्देशों के सेट (सी भाषा में) के संदर्भ का संदर्भ नहीं है, लेकिन इसमें एक छिपी हुई डेटा संरचना भी शामिल है जो सभी गैर-लोकल चरों (संदर्भित चर) का संदर्भों से बना है। इस तरह के दो टुकड़े कार्यों को बंद कर दिया जाता है। जावास्क्रिप्ट में प्रत्येक समारोह को बंद माना जा सकता है।

क्लोजर एक राज्य के साथ काम कर रहे हैं। यह कुछ हद तक "इस" के समान है कि "यह" एक समारोह के लिए राज्य भी प्रदान करता है लेकिन कार्य करता है और "यह" अलग-अलग वस्तुएं हैं ("यह" केवल एक फैंसी पैरामीटर है, और इसे स्थायी रूप से बाध्य करने का एकमात्र तरीका है कार्य बंद करना है)। जबकि "यह" और फ़ंक्शन हमेशा अलग रहते हैं, एक फ़ंक्शन को इसके बंद होने से अलग नहीं किया जा सकता है और भाषा कैप्चर किए गए चरों तक पहुंचने का कोई साधन नहीं देती है।

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

साथ ही, यह समझा जाना चाहिए कि जावास्क्रिप्ट में स्थानीय चर ढेर फ्रेम पर नहीं बनाए जाते हैं, लेकिन ढेर पर और केवल तब नष्ट हो जाते हैं जब कोई भी उनका संदर्भ नहीं दे रहा है। जब कोई फ़ंक्शन लौटाता है, तो उसके स्थानीय चर के संदर्भ कम हो जाते हैं, लेकिन वर्तमान निष्पादन के दौरान वे अभी भी गैर-शून्य हो सकते हैं, वे बंद होने का हिस्सा बन गए हैं और अभी भी इसके शब्दावली से घिरे कार्यों से संदर्भित हैं (जो केवल तभी हो सकते हैं जब संदर्भ इन नेस्टेड फ़ंक्शंस को वापस या अन्य बाहरी कोड में स्थानांतरित कर दिया गया था)।

एक उदाहरण:

function foo (initValue) {
   //This variable is not destroyed when the foo function exits.
   //It is 'captured' by the two nested functions returned below.
   var value = initValue;

   //Note that the two returned functions are created right now.
   //If the foo function is called again, it will return
   //new functions referencing a different 'value' variable.
   return {
       getValue: function () { return value; },
       setValue: function (newValue) { value = newValue; }
   }
}

function bar () {
    //foo sets its local variable 'value' to 5 and returns an object with
    //two functions still referencing that local variable
    var obj = foo(5);

    //Extracting functions just to show that no 'this' is involved here
    var getValue = obj.getValue;
    var setValue = obj.setValue;

    alert(getValue()); //Displays 5
    setValue(10);
    alert(getValue()); //Displays 10

    //At this point getValue and setValue functions are destroyed
    //(in reality they are destroyed at the next iteration of the garbage collector).
    //The local variable 'value' in the foo is no longer referenced by
    //anything and is destroyed too.
}

bar();

मुझे पता है कि पहले से ही बहुत सारे समाधान हैं, लेकिन मुझे लगता है कि इस छोटी और सरल लिपि अवधारणा को प्रदर्शित करने के लिए उपयोगी हो सकती है:

// makeSequencer will return a "sequencer" function
var makeSequencer = function() {
    var _count = 0; // not accessible outside this function
    var sequencer = function () {
        return _count++;
    }
    return sequencer;
}

var fnext = makeSequencer();
var v0 = fnext();     // v0 = 0;
var v1 = fnext();     // v1 = 1;
var vz = fnext._count // vz = undefined

जावास्क्रिप्ट फ़ंक्शंस इन तक पहुंच सकते हैं:

  1. तर्क
  2. स्थानीय (यानी, उनके स्थानीय चर और स्थानीय कार्य)
  3. पर्यावरण, जिसमें शामिल हैं:
    • डोम समेत ग्लोबल्स
    • बाहरी कार्यों में कुछ भी

यदि कोई फ़ंक्शन अपने पर्यावरण तक पहुंचता है, तो फ़ंक्शन एक बंद होता है।

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

वैश्विक वातावरण का उपयोग करने वाले बंद होने का उदाहरण:

कल्पना करें कि स्टैक ओवरफ़्लो वोट-अप और वोट-डाउन बटन ईवेंट बंद होने के रूप में कार्यान्वित किए जाते हैं, वोटअप_क्लिक और वोटडाउन_क्लिक, जिनके पास बाहरी चर तक पहुंच है, वोवेटअप और isVotedDown है, जिसे वैश्विक स्तर पर परिभाषित किया गया है। (सादगी के लिए, मैं स्टैक ओवरफ्लो के प्रश्न वोट बटन का जिक्र कर रहा हूं, उत्तर वोट बटन की सरणी नहीं।)

जब उपयोगकर्ता वोटअप बटन पर क्लिक करता है, तो वोटUp_click फ़ंक्शन जांचता है कि क्या वोट किया गया है या यह निर्धारित करने के लिए सत्य है कि वोट करना है या केवल नीचे वोट रद्द करना है या नहीं। फंक्शन वोटअप_क्लिक एक बंद है क्योंकि यह अपने पर्यावरण तक पहुंच रहा है।

var isVotedUp = false;
var isVotedDown = false;

function voteUp_click() {
  if (isVotedUp)
    return;
  else if (isVotedDown)
    SetDownVote(false);
  else
    SetUpVote(true);
}

function voteDown_click() {
  if (isVotedDown)
    return;
  else if (isVotedUp)
    SetUpVote(false);
  else
    SetDownVote(true);
}

function SetUpVote(status) {
  isVotedUp = status;
  // Do some CSS stuff to Vote-Up button
}

function SetDownVote(status) {
  isVotedDown = status;
  // Do some CSS stuff to Vote-Down button
}

इन सभी चार कार्यों को बंद कर दिया गया है क्योंकि वे सभी अपने पर्यावरण तक पहुंचते हैं।


मैंने थोड़ी देर पहले बंद ब्लॉग समझाते हुए एक ब्लॉग पोस्ट लिखा था। यहाँ है कि मैं क्या करने के मामले में बंद के बारे में कहा है कि क्यों आप एक चाहेंगे।

क्लोजर एक फ़ंक्शन को लगातार रखने के लिए एक तरीका है , निजी चर - यानी वेरिएबल्स जो केवल एक फ़ंक्शन के बारे में जानता है, जहां यह पिछले समय से जानकारी का ट्रैक रख सकता है।

उस अर्थ में, उन्होंने एक समारोह को निजी विशेषताओं वाले ऑब्जेक्ट की तरह थोड़ा कार्य करने दिया।

पूर्ण पद:

तो इन बंद चीजें क्या हैं?


सवाल को गंभीरता से लेते हुए, हमें पता होना चाहिए कि एक सामान्य 6 वर्षीय व्यक्ति संज्ञानात्मक रूप से सक्षम है, हालांकि स्वीकार्य रूप से, जो जावास्क्रिप्ट में रूचि रखता है वह इतना सामान्य नहीं है।

बचपन के विकास पर: 5 से 7 साल यह कहता है:

आपका बच्चा दो-चरणीय दिशाओं का पालन करने में सक्षम होगा। उदाहरण के लिए, यदि आप अपने बच्चे से कहते हैं, "रसोई घर जाओ और मुझे एक कचरा बैग प्राप्त करें" वे उस दिशा को याद रखने में सक्षम होंगे।

हम इस उदाहरण का उपयोग बंद करने की व्याख्या करने के लिए कर सकते हैं, जैसा कि निम्नानुसार है:

रसोईघर एक बंद है जिसमें एक स्थानीय चर है, जिसे trashBags कहा जाता है। रसोई के अंदर एक समारोह है जिसे getTrashBag कहा जाता है जिसे एक कचरा बैग मिलता है और इसे वापस कर देता है।

हम जावास्क्रिप्ट में इस तरह कोड कर सकते हैं:

function makeKitchen() {
  var trashBags = ['A', 'B', 'C']; // only 3 at first

  return {
    getTrashBag: function() {
      return trashBags.pop();
    }
  };
}

var kitchen = makeKitchen();

console.log(kitchen.getTrashBag()); // returns trash bag C
console.log(kitchen.getTrashBag()); // returns trash bag B
console.log(kitchen.getTrashBag()); // returns trash bag A

आगे के अंक बताते हैं कि बंद क्यों दिलचस्प हैं:

  • प्रत्येक बार makeKitchen() कहा जाता है, एक नया बंद अपने स्वयं के अलग trashBags के साथ बनाया जाता है।
  • trashBags वैरिएबल प्रत्येक रसोई के अंदर स्थानीय है और बाहर पहुंच योग्य नहीं है, लेकिन getTrashBag प्रॉपर्टी पर आंतरिक फ़ंक्शन के पास इसका उपयोग होता है।
  • प्रत्येक फंक्शन कॉल बंद हो जाती है, लेकिन बंद होने के अंदर से बंद होने तक कोई आंतरिक आवश्यकता नहीं होती है, जिसे बंद करने के अंदर से एक्सेस किया जा सकता है। getTrashBag फ़ंक्शन के साथ ऑब्जेक्ट को वापस करने से यह यहां होता है।

ठीक है, 6 साल के बंद प्रशंसक। क्या आप बंद करने का सबसे सरल उदाहरण सुनना चाहते हैं?

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

यहां बताया गया है कि मैं अपनी विमान कहानी को कोड में कैसे परिवर्तित कर सकता हूं।

var plane = function(defaultAirport) {

  var lastAirportLeft = defaultAirport;

  var car = {
    driver: {
      startAccessPlaneInfo: function() {
        setInterval(function() {
          console.log("Last airport was " + lastAirportLeft);
        }, 2000);
      }
    }
  };
  car.driver.startAccessPlaneInfo();

  return {
    leaveTheAirport: function(airPortName) {
      lastAirportLeft = airPortName;
    }
  }
}("Boryspil International Airport");

plane.leaveTheAirport("John F. Kennedy");


छः वर्षीय के लिए एक जवाब (मानते हुए कि वह जानता है कि कोई फ़ंक्शन क्या है और क्या चर है, और कौन सा डेटा है):

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

function the_closure() {
  var x = 4;
  return function () {
    return x; // Here, we look back inside the_closure for the value of x
  }
}

var myFn = the_closure();
myFn(); //=> 4

इसे समझाने का एक और वास्तव में सरल तरीका दायरे के मामले में है:

जब भी आप एक बड़े दायरे के अंदर एक छोटा सा गुंजाइश बनाते हैं, तो छोटे दायरे हमेशा बड़े दायरे में क्या देख पाएंगे।


एक 6 वर्षीय के पिता के रूप में, वर्तमान में युवा बच्चों को पढ़ाना (और कोई औपचारिक नौसिखिया बिना किसी औपचारिक शिक्षा के कोडिंग के लिए कोडिंग की आवश्यकता होगी), मुझे लगता है कि सबक हाथ से खेलने के माध्यम से सबसे अच्छा होगा। अगर 6 वर्षीय यह समझने के लिए तैयार है कि क्या बंद है, तो वे खुद को जाने के लिए पुरानी हैं। मैं jsfiddle.net में कोड चिपकाने का सुझाव देता हूं, थोड़ा सा समझाता हूं, और उन्हें एक अद्वितीय गीत बनाने के लिए अकेला छोड़ देता हूं। नीचे वर्णित पाठ शायद 10 साल के लिए अधिक उपयुक्त है।

function sing(person) {

    var firstPart = "There was " + person + " who swallowed ";

    var fly = function() {
        var creature = "a fly";
        var result = "Perhaps she'll die";
        alert(firstPart + creature + "\n" + result);
    };

    var spider = function() {
        var creature = "a spider";
        var result = "that wiggled and jiggled and tickled inside her";
        alert(firstPart + creature + "\n" + result);
    };

    var bird = function() {
        var creature = "a bird";
        var result = "How absurd!";
        alert(firstPart + creature + "\n" + result);
    };

    var cat = function() {
        var creature = "a cat";
        var result = "Imagine That!";
        alert(firstPart + creature + "\n" + result);
    };

    fly();
    spider();
    bird();
    cat();
}

var person="an old lady";

sing(person);

निर्देश

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

कोड: उपरोक्त सभी लेखन कोड कहा जाता है । यह जावास्क्रिप्ट में लिखा गया है।

जावास्क्रिप्ट: जावास्क्रिप्ट एक भाषा है। अंग्रेजी या फ्रेंच या चीनी की तरह भाषाएं हैं। कंप्यूटर और अन्य इलेक्ट्रॉनिक प्रोसेसर द्वारा कई भाषाएं समझी जाती हैं। किसी कंप्यूटर द्वारा जावास्क्रिप्ट को समझने के लिए इसे एक दुभाषिया की आवश्यकता होती है। कल्पना कीजिए कि एक शिक्षक जो केवल रूसी बोलता है वह स्कूल में अपनी कक्षा पढ़ाने के लिए आता है। जब शिक्षक कहते हैं "все садятся", कक्षा समझ में नहीं आती। लेकिन सौभाग्य से आपके वर्ग में एक रूसी छात्र है जो हर किसी को बताता है कि "सब लोग बैठते हैं" - तो आप सब करते हैं। कक्षा एक कंप्यूटर की तरह है और रूसी छात्र दुभाषिया है। जावास्क्रिप्ट के लिए सबसे आम दुभाषिया को ब्राउज़र कहा जाता है।

ब्राउजर: जब आप किसी वेबसाइट पर जाने के लिए कंप्यूटर, टैबलेट या फोन पर इंटरनेट से कनेक्ट होते हैं, तो आप ब्राउज़र का उपयोग करते हैं। जिन उदाहरणों को आप जानते हैं वे इंटरनेट एक्सप्लोरर, क्रोम, फ़ायरफ़ॉक्स और सफारी हैं। ब्राउजर जावास्क्रिप्ट को समझ सकता है और कंप्यूटर को बता सकता है कि उसे क्या करना है। जावास्क्रिप्ट निर्देशों को फ़ंक्शन कहा जाता है।

समारोह: जावास्क्रिप्ट में एक फ़ंक्शन एक कारखाने की तरह है। यह केवल एक मशीन के साथ एक छोटा सा कारखाना हो सकता है। या इसमें कई अन्य छोटी फैक्ट्रियां हो सकती हैं, जिनमें से कई मशीनें अलग-अलग नौकरियां कर रही हैं। वास्तविक जीवन कपड़ों के कारखाने में आपके पास थैले के कपड़े और बॉबिन के रीम हो सकते हैं और टी-शर्ट और जींस आ रहे हैं। हमारा जावास्क्रिप्ट फैक्ट्री केवल डेटा को संसाधित करता है, यह एक छेद ड्रिल या मेटल पिघला नहीं सकता है। हमारे जावास्क्रिप्ट कारखाने में डेटा चला जाता है और डेटा आता है।

यह सभी डेटा सामान थोड़ा उबाऊ लगता है, लेकिन यह वास्तव में बहुत अच्छा है; हमारे पास एक ऐसा कार्य हो सकता है जो रोबोट को रात के खाने के लिए क्या करना है। मान लें कि मैं आपको और आपके दोस्त को अपने घर में आमंत्रित करता हूं। आपको चिकन पैरों को सबसे अच्छा पसंद है, मुझे सॉसेज पसंद है, आपका दोस्त हमेशा चाहता है कि आप क्या चाहते हैं और मेरा दोस्त मांस नहीं खाता है।

मुझे खरीदारी करने के लिए समय नहीं मिला है, इसलिए फंक्शन को निर्णय लेने के लिए फ्रिज में हमारे पास क्या पता है। प्रत्येक घटक के पास एक अलग खाना पकाने का समय होता है और हम एक ही समय में रोबोट द्वारा सब कुछ गर्म करने के लिए चाहते हैं। हमें फ़ंक्शन को इस बारे में डेटा प्रदान करने की आवश्यकता है कि हम क्या पसंद करते हैं, फ़ंक्शन फ्रिज पर 'बात' कर सकता है, और फ़ंक्शन रोबोट को नियंत्रित कर सकता है।

एक समारोह में आमतौर पर एक नाम, कोष्ठक और ब्रेसिज़ होते हैं। ऐशे ही:

function cookMeal() {  /*  STUFF INSIDE THE FUNCTION  */  }

कि नोट /*...*/और //कोड रोक ब्राउज़र द्वारा पढ़ा जा रहा है।

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

PARENTHESES: "Parentheses" या ()कारखाने में जानकारी के पैकेट भेजने के लिए जावास्क्रिप्ट फ़ंक्शन फैक्ट्री के दरवाजे या सड़क में एक पोस्ट बॉक्स पर लेटर बॉक्स हैं। कभी-कभी पोस्टबॉक्स को उदाहरण के लिए चिह्नित किया जा सकता है, cookMeal(you, me, yourFriend, myFriend, fridge, dinnerTime)इस मामले में आप जानते हैं कि आपको यह डेटा क्या देना है।

ब्रैस: "ब्रेसिज़" जो इस तरह दिखते हैं {}हमारे कारखाने की टिंटेड खिड़कियां हैं। कारखाने के अंदर से आप देख सकते हैं, लेकिन बाहर से आप अंदर नहीं देख सकते हैं।

लंबे कोड उदाहरण ऊपर

हमारा कोड शब्द समारोह के साथ शुरू होता है , इसलिए हम जानते हैं कि यह एक है! फिर फ़ंक्शन का नाम गाता है - यह मेरा स्वयं का विवरण है कि फ़ंक्शन क्या है। फिर कोष्ठक () । एक समारोह के लिए कोष्ठक हमेशा वहाँ रहते हैं। कभी-कभी वे खाली होते हैं, और कभी-कभी उनके पास कुछ भी होता है। इसमें एक शब्द है (person):। इसके बाद इस तरह एक ब्रेस है {। यह समारोह गायन () की शुरुआत को चिह्नित करता है । इसमें एक साझेदार है जो इस तरह गाते हैं ()}

function sing(person) {  /* STUFF INSIDE THE FUNCTION */  }

तो इस समारोह में गायन के साथ कुछ करने के लिए हो सकता है, और किसी व्यक्ति के बारे में कुछ डेटा की आवश्यकता हो सकती है। इसमें उस डेटा के साथ कुछ करने के लिए निर्देश हैं।

अब, समारोह के बाद () , कोड के अंत के पास लाइन है

var person="an old lady";

VARIABLE: अक्षर "चर" के लिए var स्टैंड। एक चर एक लिफाफे की तरह है। बाहर इस लिफाफे को "व्यक्ति" चिह्नित किया गया है। अंदर पर इसमें हमारे फ़ंक्शन की जानकारी के साथ पेपर की एक पर्ची होती है, कुछ अक्षरों और रिक्त स्थान स्ट्रिंग के टुकड़े (इसे एक स्ट्रिंग कहा जाता है) की तरह मिलते हैं जो "पुरानी महिला" पढ़ने वाला वाक्यांश बनाते हैं। हमारे लिफाफे में अन्य प्रकार की चीजें हो सकती हैं जैसे संख्याएं (पूर्णांक कहा जाता है), निर्देश (फ़ंक्शन कहा जाता है), सूचियां ( सरणी कहा जाता है )। चूंकि यह चर सभी ब्रेसिज़ के बाहर लिखा गया है {}, और क्योंकि जब आप ब्रेसिज़ के अंदर होते हैं तो आप टिंटेड विंडो के माध्यम से देख सकते हैं, यह चर कोड में कहीं से भी देखा जा सकता है। हम इसे 'ग्लोबल वैरिएबल' कहते हैं।

वैश्विक वैरिएबल : व्यक्ति एक वैश्विक चर है, जिसका अर्थ है कि यदि आप "एक बूढ़े औरत" से "एक जवान आदमी" से अपना मूल्य बदलते हैं, तो व्यक्ति तब तक एक युवा व्यक्ति बनेगा जब तक आप इसे फिर से बदलने का फैसला नहीं करते और कोई अन्य कार्य कोड देख सकता है कि यह एक जवान आदमी है। प्रेस F12बटन या एक ब्राउज़र के डेवलपर कंसोल खोलें और "व्यक्ति" टाइप देखने के लिए क्या यह मान है करने के लिए विकल्प सेटिंग्स को देखो। person="a young man"इसे बदलने के लिए टाइप करें और फिर यह देखने के लिए फिर से "व्यक्ति" टाइप करें कि यह बदल गया है।

इसके बाद हमारे पास लाइन है

sing(person);

यह लाइन फ़ंक्शन को कॉल कर रही है, जैसे कि यह कुत्ते को बुला रही थी

" गाओ , आओ और व्यक्ति हो जाओ !"

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

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

क्लोजर: बंद छोटे कार्य हैं जो बड़े गायन () फ़ंक्शन के अंदर हैं । बड़े कारखाने के अंदर छोटी कारखानों। उनमें से प्रत्येक का अपना ब्रेसिज़ होता है जिसका मतलब है कि उनके अंदर के चर बाहर से नहीं देखे जा सकते हैं। यही कारण है कि चर (के नाम है प्राणी और परिणाम ) बंद में लेकिन विभिन्न मूल्यों के साथ दोहराया जा सकता है। यदि आप कंसोल विंडो में इन चर नामों को टाइप करते हैं, तो आपको इसका मूल्य नहीं मिलेगा क्योंकि यह टिंटेड विंडो की दो परतों से छिपा हुआ है।

बंद सभी जानते हैं कि गायन () फ़ंक्शन का चर पहला नाम कहलाता है, क्योंकि वे अपनी टिंटेड विंडो से देख सकते हैं।

बंद होने के बाद लाइनें आती हैं

fly();
spider();
bird();
cat();

गायन () फ़ंक्शन इन कार्यों में से प्रत्येक को दिए गए क्रम में कॉल करेगा। फिर गायन () फ़ंक्शन का काम किया जाएगा।


ठीक है, 6 साल के बच्चे के साथ बात करते हुए, मैं संभवतः निम्नलिखित संगठनों का उपयोग करूंगा।

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

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

एक उन्नत बच्चे के लिए मैं निम्नलिखित की तरह कुछ डालूँगा। यह सही नहीं है, लेकिन यह आपको इस बारे में महसूस करता है कि यह क्या है:

function playingInBrothersRoom (withToys) {
  // We closure toys which we played in the brother's room. When he come back and lock the door
  // your brother is supposed to be into the outer [[scope]] object now. Thanks god you could communicate with him.
  var closureToys = withToys || [],
      returnToy, countIt, toy; // Just another closure helpers, for brother's inner use.

  var brotherGivesToyBack = function (toy) {
    // New request. There is not yet closureToys on brother's hand yet. Give him a time.
    returnToy = null;
    if (toy && closureToys.length > 0) { // If we ask for a specific toy, the brother is going to search for it.

      for ( countIt = closureToys.length; countIt; countIt--) {
        if (closureToys[countIt - 1] == toy) {
          returnToy = 'Take your ' + closureToys.splice(countIt - 1, 1) + ', little boy!';
          break;
        }
      }
      returnToy = returnToy || 'Hey, I could not find any ' + toy + ' here. Look for it in another room.';
    }
    else if (closureToys.length > 0) { // Otherwise, just give back everything he has in the room.
      returnToy = 'Behold! ' + closureToys.join(', ') + '.';
      closureToys = [];
    }
    else {
      returnToy = 'Hey, lil shrimp, I gave you everything!';
    }
    console.log(returnToy);
  }
  return brotherGivesToyBack;
}
// You are playing in the house, including the brother's room.
var toys = ['teddybear', 'car', 'jumpingrope'],
    askBrotherForClosuredToy = playingInBrothersRoom(toys);

// The door is locked, and the brother came from the school. You could not cheat and take it out directly.
console.log(askBrotherForClosuredToy.closureToys); // Undefined

// But you could ask your brother politely, to give it back.
askBrotherForClosuredToy('teddybear'); // Hooray, here it is, teddybear
askBrotherForClosuredToy('ball'); // The brother would not be able to find it.
askBrotherForClosuredToy(); // The brother gives you all the rest
askBrotherForClosuredToy(); // Nothing left in there

जैसा कि आप देख सकते हैं, कमरे में छोड़े गए खिलौने अभी भी भाई के माध्यम से सुलभ हैं और इससे कोई फर्क नहीं पड़ता कि कमरा लॉक है या नहीं। इसके साथ खेलने के लिए यहां एक jsbin है।


मेरे पास एक साधारण मुद्दा था, लेकिन मैं इस सवाल के जवाब से परेशान था।

मुझे एक जावास्क्रिप्ट फ़ाइल (myvariables.js) में एक अन्य जावास्क्रिप्ट फ़ाइल (main.js) में परिभाषित एक चर (myVar1) का उपयोग करना पड़ा।

इसके लिए मैंने नीचे किया था:

HTML फ़ाइल में जावास्क्रिप्ट कोड को सही क्रम में, myvariables.js पहले लोड किया गया, फिर main.js:

<html>
    <body onload="bodyReady();" >

        <script src="myvariables.js" > </script>
        <script src="main.js" > </script>

        <!-- Some other code -->
    </body>
</html>

फ़ाइल: myvariables.js

var myVar1 = "I am variable from myvariables.js";

फ़ाइल: main.js

// ...
function bodyReady() {
    // ...
    alert (myVar1);    // This shows "I am variable from myvariables.js", which I needed
    // ...
}
// ...

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

यह मेरा दिन बचाया। आशा है कि ये आपकी मदद करेगा।







javascript function variables scope closures