2011-12-13 20 views
11

मैं जावास्क्रिप्ट बंद करने पर मोज़िलास डेवलपर साइट देख रहा था और उनके पास कोड का यह उदाहरण था।जावास्क्रिप्ट में रिटर्निंग फ़ंक्शन, स्कोप और क्लोजर को समझना

function makeAdder(x){ 
    return function (y) { 
     console.log(y + " this is y") 
     console.log(x + " this is x") 
     return x + y; 
     } 
} 
var add10 = makeAdder(10); 
console.log(add10(2)); // 12 

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

उत्तर

13

makeAdder एक फ़ंक्शन देता है जिसमें आप y पैरामीटर पास कर सकते हैं। यह आमंत्रण के समय सेट किया गया है, x के विपरीत जो कि नए कार्य के निर्माण के समय निर्धारित है (makeAdder के आमंत्रण के समय)।

इस उदाहरण के मामले के लिए, उत्पादन लिखा होने के बराबर है:

function add10(y) { 
    return 10 + y; 
} 

console.log(add10(2)); // 12 

कुछ भी नया नहीं यहाँ चल रहा है। नमूना कोड मुख्य रूप से यह वर्णन करने की कोशिश कर रहा है कि x के लिए एक बंद किया जा रहा है।

तो makeAdder, यहाँ, जिसे उपयुक्त नाम है: जब आप इसे करने के लिए 10 पास, तो यह आपको एक समारोह है कि सब कुछ करने के लिए 10 जोड़ देगा आपको लगता है कि नए कार्य को पारित देता है।

var add10 = makeAdder(10); 
var add20 = makeAdder(20); 

console.log(add10(1) + add20(1)); // 32 

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

एक असली दुनिया परिदृश्य कुछ इस तरह हो सकता है:

var buttons = document.getElementsByClassName('myButton'); 
for(var i = 0; i < buttons.length; i++) { 
    buttons[i].onclick = function() { 
     alert('You clicked button ' + i); 
    }; 
} 

उपरोक्त कोड में, i पूरे सेट के माध्यम से दोहराया है इससे पहले कि बटन के किसी भी क्लिक किया जाता है। इसलिए, सभी बटन जो भी buttons.length है उसे अलर्ट करेंगे। इसके बजाय, आप निम्न कर सकता है:

var makeAlert = function(x) { 
    return function() { 
     alert('You clicked button ' + x); 
    }; 
}; 

for(var i = 0; i < buttons.length; i++) { 
    buttons[i].onclick = makeAlert(i); 
} 

अंतर है कि यहाँ i बटन क्लिक होने प्रयोग किया जाता है नहीं किया जा रहा है (जो पूरे यात्रा के बाद हो जाएगा), लेकिन यह यात्रा के दौरान प्रयोग किया जाता है, एक समय में जब i प्रत्येक बटन के लिए एक अलग मूल्य होगा।

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

for(var i = 0; i < buttons.length; i++) { 
    buttons[i].onclick = (function(x) { 
     return function() { 
      alert('You clicked button ' + x); 
     }; 
    })(i); 
} 
+0

मैं देख रहा हूँ, मेरे मस्तिष्क अभी भी इसे पाने के लिए कोशिश कर रहा है, im बस की कोशिश कर रहा: लेकिन क्योंकि यह एक कारखाना है (मान 2 के साथ पहले से कॉन्फ़िगर) एक समारोह है कि एक पैरामीटर लेता लौटने, हम इसे जब हम इसे चलाने के अनुकूलित कर सकते हैं देखें कि y कैसे पारित किया गया है या सेट किया गया है जब इसका कोई संदर्भ नहीं है क्योंकि मेरे सिर में add10 (3) कहता है कि आपकी सेटिंग एक्स क्यों नहीं ?? यह काफी उलझन में प्रतीत होता है :( – mustafa

+1

नहीं, 'x' कॉल 'मेकएडर (10)' में' 10' पर सेट किया गया है। 'Y' कॉल 'add10 (2)' –

+0

पर '2' पर सेट है लेकिन नहीं होना चाहिए makeAdder (10, 2) वही काम करते हैं? या हम जो अनिवार्य रूप से करते हैं वह हैडर (10)। (2)? आपको लोगों द्वारा बहुत बहुत धन्यवाद :) – mustafa

1

फ़ंक्शन makeAdder इसे कॉल करते समय एक फ़ंक्शन देता है। यह कार्य makeAdder रिटर्न एक पैरामीटर स्वीकार करता है; जिसे y कहा जाता है।

परिवर्तनीय y केवल makeAdder द्वारा दिए गए फ़ंक्शन के आमंत्रण के दौरान मौजूद है। यह हर बार बनाया जाता है कहा जाता है, और जब समारोह लौटाता है तो नष्ट हो जाता है।

दूसरी तरफ x परिवर्तनीय makeAdder कहा जाता है, और makeAdder रिटर्न द्वारा बनाए गए बंद होने के कारण जारी रहता है। जब समारोह में कोई और संदर्भ वापस नहीं आया तो यह नष्ट हो जाएगा।

1

तो add10 = makeAdder(10); वास्तव में इस समारोह लौटा रहा है: नीचे दिए गए कोड को अनिवार्य रूप से ऊपर कोड के बराबर है

function(y) { 
    console.log(y + " this is y") 
    console.log("10" + " this is x") 
    return 10 + y; 
} 

फिर add10(2) कि समारोह बुला रहा है, 2 हर जगह साथ y की जगह:

console.log("2" + " this is y") 
    console.log("10" + " this is x") 
    return 10 + 2; 
+0

ठीक है, लेकिन आप अपने लक्ष्यीकरण वाई को कैसे जानते हैं, एक नौसिखिया की तरह लगने के लिए खेद है, यह देखने की कोशिश कर रहा है कि आप कैसे जानते होंगे कि आप सही पैरामीटर तक पहुंच रहे थे, मुझे लगता है कि मेरी समस्या वापस आ रही है वर्र्स इत्यादि के विपरीत कार्य .. – mustafa

+0

अच्छी तरह से पहले एक्स को हर जगह 10 के साथ बदलने और उस कार्य को जोड़ने के लिए 10 को जोड़ने का विचार करें। पहली बार जब आप कॉल कर रहे हैं तो जोड़ा गया है कि आप पहले फंक्शन को लक्षित कर रहे हैं, और दूसरी बार जब आप 'सेकेंड' फ़ंक्शन को लक्षित कर रहे हैं, तो वाई वाला एक (जिसे पहले नेस्टेड किया गया था लेकिन अब एक var को असाइन किया गया था और फिर मधुमक्खियों को बुलाया गया था)। आप असाइनमेंट करने के बाद स्वयं को देखने के लिए फ़ायरबग में console.log (add10) कर सकते हैं। – alessioalex

+0

तो यह थोड़ा सा लिखने की तरह हैडर (10)। (2)? आपको लोगों द्वारा बहुत बहुत धन्यवाद :) – mustafa

2

कार्य विशेष वस्तुओं के रूप में देखा जा सकता है जिनमें निष्पादन योग्य कोड और गुण शामिल हैं। प्रत्येक कार्य में एक विशेष [स्कोप] संपत्ति होती है जो पर्यावरण को दर्शाती है जब इसे परिभाषित किया गया था। यदि किसी फ़ंक्शन को किसी अन्य फ़ंक्शन से वापस किया जाता है तो पुराने वातावरण के लिए यह संदर्भ "बंद" में नए फ़ंक्शन द्वारा बंद कर दिया जाता है।

इसलिए जब आप var add10 = makeAdder(10) फोन क्या होता लौटे समारोह के x मूल्य 10 जो करने के लिए यह गुंजाइश है ही है, और कॉल console.log(add10(2)) प्रिंट 12 किया है।

this लेख पढ़ने पर विचार करें कि क्या बंद हो रहा है। बंद करने का एक और विस्तृत स्पष्टीकरण here पाया जा सकता है।

+0

लिंक दोस्त – mustafa

5

क्या आप के लिए पूछ रहे हैं एक समारोह है कि आप के लिए कुछ करता है:

function giveMeAFunctionThatBeeps(){ 
    return function() { 
     alert('Beep!'); 
     } 
} 

var beeper = giveMeAFunctionThatBeeps(); 

beeper(); // beeps! 

वास्तविक giveMeAFunctionThatbeeps सिर्फ एक कारखाना है कि आप एक समारोह है कि आप क्या चाहते हैं देता है।

उदाहरण वे प्रदान की है में, आप बीपर के रूप में एक ही बात कर रहे हैं लेकिन आप यह भी एक मूल्य में गुजर रहे हैं:

function giveMeAFunctionThatBeepsANumber(x){ 
    return function() { 
     alert('Beep ' + x); 
     } 
} 

यह एक बीपर (यह एक कारखाना याद है) देता है, लेकिन बीपर एक्स का मान अलर्ट करता है।

हालांकि, इस मूल्य जब आप पहली बार बीपर बनाने के लिए निर्धारित है:

var beeper = giveMeAFunctionThatBeeps(5); 

beeper(); // beeps 5! 

बीपर अब मूल्य 5 beeping फंस गया है, और हम इस बारे में कुछ नहीं कर सकते।

function giveMeAFunctionThatBeepsANumber(){ 
    return function (x) { 
     alert('Beep ' + x); 
     } 
} 

var beeper = giveMeAFunctionThatBeeps(); 

beeper(6); // beeps 6! 
beeper(7); // beeps 7! 

के रूप में अब हम हमें एक समारोह हम में एक नंबर प्लग कर देने के लिए कारखाने में पूछ रहे हैं:

अगले उदाहरण आप एक बीपर कि किसी भी संख्या बीप बनाने के लिए चाहते हैं।

फिर अंत में, मूल उदाहरण के लिए, ऊपर के दोनों संयुक्त है:

function giveMeAFunctionThatBeepsANumber(x){ 
    return function (y) { 
     alert('Beep ' + (x + y)); 
     } 
} 

var beeper = giveMeAFunctionThatBeeps(2); 

जब हम बीपर बनाते हैं तो हम 2 में के रूप में ऊपर याद रखें गुजर रहे हैं, हम इस बाद में परिवर्तित नहीं कर सकता! यह हमेशा बीप 2 होगा ...

...

beeper(6); // beeps 8! because x was set when we created it, and y is what we pass in. 
+0

के लिए धन्यवाद यह बहुत अच्छा है आपके समय – mustafa

+0

के लिए बहुत बहुत धन्यवाद, मुझे कोई चिंता नहीं हुई, मुझे बंद होने में परेशानी हुई और मुझे एक ही चीज के लिए कई टन और कई अलग-अलग स्पष्टीकरण मिल गए :) – NibblyPig

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