javascript सक्षम एचटीएमएल - जावास्क्रिप्ट कैसे काम बंद कर देता है?





15 Answers

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

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 ऑब्जेक्ट्स के साथ मेमोरी लीक का आधार है।

संरचना प्रपत्र विकिपीडिया

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

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




सवाल को गंभीरता से लेते हुए, हमें पता होना चाहिए कि एक सामान्य 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 फ़ंक्शन के साथ ऑब्जेक्ट को वापस करने से यह यहां होता है।



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

    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 के लिए बाध्य है।




ठीक है, 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");




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

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

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

पूर्ण पद:

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




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

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




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

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

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




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

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

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



मुझे समझ में नहीं आता कि जवाब यहां इतने जटिल क्यों हैं।

यहां एक बंद है:

var a = 42;

function b() { return a; }

हाँ। आप शायद उस दिन कई बार उपयोग करते हैं।


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

अब यह आपको क्या करने की अनुमति देता है और अधिक शानदार हो सकता है, अन्य उत्तरों देखें।




एक बंदरगाह वह है जहां एक आंतरिक कार्य के बाहरी कार्य में चर के लिए उपयोग होता है। यह शायद सबसे आसान एक-पंक्ति स्पष्टीकरण है जिसे आप बंद करने के लिए प्राप्त कर सकते हैं।




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

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

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. ब्राउजर लेक्सिकल एंटरप्राइज और इसकी सभी गुणों (चर) को मेमोरी में तब तक रखता है जब तक कोई आंतरिक फ़ंक्शन न हो।

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




ठीक है, 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 है।




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

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

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

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

एक उदाहरण:

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();



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

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






Related