फ़ंक्शंस जो एक फ़ंक्शन लौटाते हैं


110

मैं 'फ़ंक्शंस कि रिटर्न फ़ंक्शंस' की इस अवधारणा के साथ फंस गया हूं। मैं Stoyan Stefanov की पुस्तक 'ऑब्जेक्ट ओरिएंटेड जावास्क्रिप्ट' की बात कर रहा हूँ।

स्निपेट एक:

    function a() {
      
        alert('A!');
    
        function b(){
            alert('B!'); 
        }
    
        return b();
    }
    
    var s = a();
    alert('break');
    s();

आउटपुट:

A!
B!
break

स्निपेट दो

function a() {
  
    alert('A!');

    function b(){
        alert('B!'); 
    }

    return b;
}

var s = a();
alert('break');
s();
आउटपुट:

A!
break
B!

क्या कोई कृपया मुझे लौटने bऔर b()उपरोक्त स्निपेट के बीच का अंतर बता सकता है ?


2
आप ध्यान देंगे कि पहला स्निपेट s () पर एक त्रुटि देता है;
weirdalsuperfan

जवाबों:


122

फ़ंक्शन (कोष्ठक के बिना) के लिए एक चर असाइन करना फ़ंक्शन के संदर्भ को कॉपी करता है। फ़ंक्शन नाम के अंत में कोष्ठक लाना, फ़ंक्शन को कॉल करता है, फ़ंक्शंस रिटर्न मान लौटाता है।

डेमो

function a() {
    alert('A');
}
//alerts 'A', returns undefined

function b() {
    alert('B');
    return a;
}
//alerts 'B', returns function a

function c() {
    alert('C');
    return a();
}
//alerts 'C', alerts 'A', returns undefined

alert("Function 'a' returns " + a());
alert("Function 'b' returns " + b());
alert("Function 'c' returns " + c());

आपके उदाहरण में, आप फ़ंक्शन के भीतर फ़ंक्शन को भी परिभाषित कर रहे हैं। जैसे कि:

function d() {
    function e() {
        alert('E');
    }
    return e;
}
d()();
//alerts 'E'

फ़ंक्शन अभी भी कॉल करने योग्य है। यह अभी भी मौजूद है। इसका उपयोग हर समय जावास्क्रिप्ट में किया जाता है। कार्यों को अन्य मूल्यों की तरह ही पास किया जा सकता है । निम्नलिखित को धयान मे रखते हुए:

function counter() {
    var count = 0;
    return function() {
        alert(count++);
    }
}
var count = counter();
count();
count();
count();

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


स्निपेट वन: var Hero = {name: 'Rafaelo', sayName: function () {return hero.name; }, nayName: hero.sayName} hero.nayName (); स्निपेट दो: var Hero = {name: 'Rafaelo', sayName: function () {return hero.name; }, nayName: this.sayName} hero.nayName (); पहला स्निपेट मुझे सही आउटपुट देता है जबकि दूसरा नहीं। क्यों? सादर।
कैफ़ेकोरिडॉर

thisकेवल एक फ़ंक्शन बॉडी के अंदर कुछ का मतलब है, अन्यथा यह वैश्विक है। आप जो कह रहे हैं, this.sayNameवह यह है कि आप वैश्विक वैरिएबल चाहते हैं sayNameजो मौजूद नहीं है, यह अपरिभाषित है, इसलिए कॉल करने योग्य नहीं है।
kzh

7
मैं d () () द्वारा भ्रमित था; पहले लेकिन फिर एहसास हुआ कि पहला () डी को कॉल करता है और दूसरा () डी का रिटर्न वैल्यू कहता है, जो ई है।
स्कड

1
आठ साल बाद और यह अभी भी प्रासंगिक है!
ब्रैड वेंडरबश

45

फ़ंक्शन का नाम दिए बिना फ़ंक्शन का ()संदर्भ लौटाता है, जिसे आपके द्वारा किए गए अनुसार असाइन किया जा सकता है var s = a()sअब फ़ंक्शन का संदर्भ है b(), और कॉलिंग s()कार्यात्मक रूप से कॉलिंग के बराबर है b()

// Return a reference to the function b().
// In your example, the reference is assigned to var s
return b;

फ़ंक्शन को ()रिटर्न स्टेटमेंट के साथ कॉल करने से फ़ंक्शन निष्पादित होता है, और फ़ंक्शन द्वारा जो भी मान लौटाया गया था, वह वापस आ जाता है। यह कॉलिंग के समान है var x = b();, लेकिन b()आप का रिटर्न वैल्यू असाइन करने के बजाय इसे कॉलिंग फ़ंक्शन से वापस कर रहे हैं a()। यदि फ़ंक्शन b()स्वयं एक मान नहीं लौटाता है, तो कॉल undefinedजो भी अन्य काम करता है, उसके बाद लौटता है b()

// Execute function b() and return its value
return b();
// If b() has no return value, this is equivalent to calling b(), followed by
// return undefined;

1
सभी उत्तरों में से, मुझे इसकी सरलता के कारण आपका उत्तर अधिक पसंद आया।
अनार खलीलोव

अच्छे से कहा! इस उत्तर को समझना बहुत आसान है।
एंड्रयूसाइथेइसर

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

37

return b(); फ़ंक्शन को कॉल करता है b (), और उसका परिणाम देता है।

return b; फ़ंक्शन बी का संदर्भ देता है, जिसे आप बाद में कॉल करने के लिए एक चर में स्टोर कर सकते हैं।


17

रिटर्निंग b एक फंक्शन ऑब्जेक्ट लौटा रहा है। जावास्क्रिप्ट में, फ़ंक्शन किसी भी अन्य ऑब्जेक्ट की तरह सिर्फ ऑब्जेक्ट हैं। यदि आपको लगता है कि सहायक नहीं है, तो बस "वस्तु" शब्द को "चीज़" से बदल दें। आप किसी फंक्शन से किसी भी ऑब्जेक्ट को वापस कर सकते हैं। आप एक सही / गलत मान वापस कर सकते हैं। एक पूर्णांक (1,2,3,4 ...)। आप एक स्ट्रिंग वापस कर सकते हैं। आप कई गुणों के साथ एक जटिल वस्तु वापस कर सकते हैं। और आप एक फ़ंक्शन वापस कर सकते हैं। एक समारोह सिर्फ एक चीज है।

आपके मामले में, रिटर्निंग bचीज़ लौटती है, चीज़ एक कॉल करने योग्य फ़ंक्शन है। कॉल b()करने योग्य फ़ंक्शन द्वारा लौटाया गया मान लौटाता है।

इस कोड पर विचार करें:

function b() {
   return 42;
}

उपरोक्त परिभाषा का उपयोग करते हुए, return b();42 मान लौटाता है। दूसरी ओर return b;एक फ़ंक्शन देता है, जो स्वयं 42 का मान लौटाता है। वे दो अलग-अलग चीजें हैं।


4
यह वापस आ जाना चाहिए 42;)
c69

4

जब आप वापस आते हैं b, तो यह फ़ंक्शन बी का एक संदर्भ है, लेकिन इस समय निष्पादित नहीं किया जा रहा है।

जब आप वापस लौटते हैं b(), तो आप फ़ंक्शन को निष्पादित कर रहे हैं और उसका मान लौटा रहे हैं।

प्रयास करें alerting typeof(s)अपने उदाहरण में। स्निपेट बी आपको 'फंक्शन' देगा। स्निपेट आपको क्या देगा?


पहले एक 'अपरिभाषित' देता है। क्या इसका मतलब है कि रिटर्न बी () पूरी तरह से बेकार है? इसके अलावा, दूसरे स्निपेट में, फ़ंक्शन बी निजी है। फिर हम फ़ंक्शन के बाहर संदर्भ तक कैसे पहुंच सकते हैं? कृपया मुझे एक लिंक प्रदान करें जो यदि संभव हो तो इस अवधारणा को स्पष्ट रूप से समझाता है। धन्यवाद!
कैफिकॉरिडोर

मुझे पहले वाले का जवाब मिल गया। फ़ंक्शन b () में 1 + 2 लौटाएं और टाइपो संख्या दिखाता है। धन्यवाद।
Cafecorridor

मुझे ख़ुशी है कि तुमने उसे ढूँढ लिया! निजी फ़ंक्शन के लिए: यह दूसरे उदाहरण में वास्तव में निजी नहीं है क्योंकि आपने इसे पहले ही वापस कर दिया है। वास्तव में, इसे सौंपा गया है s। हालांकि return thisइसके बजाय प्रयास करें return b... आप s.b()तब ऐसा करने में सक्षम होंगे ;)
vzwick

मैं यह सुनिश्चित करने के लिए कोशिश करेंगे। जावास्क्रिप्ट में अभी तक इस अवधारणा तक नहीं पहुंचे हैं। शायद कुछ दिनों में। धन्यवाद! :)
२३:०४ पर Cafecorridor

फ़ंक्शन a () {अलर्ट ("ए!"); समारोह बी () {चेतावनी ("बी!"); } बी वापस; } var s = (a); हटा दें; रों (); ---- अंत ---- क्या जावास्क्रिप्ट में संदर्भ की अवधारणा जावा के समान है? यहाँ मैंने फंक्शन () को डिलीट कर दिया है और फिर भी एस () बी () को कॉल करता है। तो क्या मैं कह सकता हूँ कि s में b की एक प्रति है और b () a () में परिभाषित नहीं है?
Cafecorridor

2

प्रकार की तरह फ़ंक्शन की कल्पना करें, एक इंट की तरह। आप किसी फ़ंक्शन में इनट्स वापस कर सकते हैं। आप फ़ंक्शन भी वापस कर सकते हैं, वे "फ़ंक्शन" प्रकार के ऑब्जेक्ट हैं।

अब वाक्यविन्यास समस्या: क्योंकि फ़ंक्शन मान लौटाता है, आप किसी फ़ंक्शन को कैसे लौटा सकते हैं और यह मान वापस नहीं कर रहा है?

कोष्ठक को छोड़ कर! क्योंकि कोष्ठक के बिना, कार्य निष्पादित नहीं किया जाएगा! इसलिए:

return b;

"फ़ंक्शन" लौटाएगा (कल्पना करें कि जैसे आप एक नंबर लौटा रहे हैं), जबकि:

return b();

पहले फ़ंक्शन को निष्पादित करता है फिर इसे निष्पादित करके प्राप्त मूल्य लौटाता है, यह एक बड़ा अंतर है!


दूसरे स्निपेट में, फ़ंक्शन बी निजी है। फिर हम फ़ंक्शन के बाहर संदर्भ तक कैसे पहुंच सकते हैं? क्या कोई नियम समान हैं?
कैफ़ेकोरिडोर

यदि आप उन्हें साझा करते हैं तो जावास्क्रिप्ट में वस्तुएँ (इसमें फ़ंक्शंस शामिल हैं) अब निजी नहीं हैं।
kzh

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

2

एक चर बनाएं :

var thing1 = undefined;

एक समारोह घोषित करें :

function something1 () {
    return "Hi there, I'm number 1!";
}

(हमारे पहले चर) के मूल्य को सचेत करें thing1:

alert(thing1); // Outputs: "undefined".

अब, हम चाहते थे कि अगर thing1एक होने के लिए संदर्भ कार्य करने के लिए something1, जिसका अर्थ यह हमारे बनाई समारोह के रूप में एक ही बात होगी, हम करेंगे:

thing1 = something1;

हालाँकि, यदि हम फ़ंक्शन का return मान चाहते हैं, तो हमें इसे निष्पादित फ़ंक्शन का रिटर्न मान असाइन करना होगा। आप कोष्ठक का उपयोग करके फ़ंक्शन को निष्पादित करते हैं:

thing1 = something1(); // Value of thing1: "Hi there, I'm number 1!" 

-1

स्निपेट एक:

function a() {
  
    alert('A!');

    function b(){
        alert('B!'); 
    }

    return b(); //return nothing here as b not defined a return value
}

var s = a(); //s got nothing assigned as b() and thus a() return nothing.
alert('break');
s(); // s equals nothing so nothing will be executed, JavaScript interpreter will complain

कथन 'बी' ('बी') 'बी' नामक फ़ंक्शन को निष्पादित करने का मतलब है जो पाठ 'बी' के साथ एक संवाद बॉक्स दिखाता है!

कथन 'रिटर्न b ();) 'बी' नाम के एक फंक्शन को अंजाम देने का मतलब है और फिर किस फंक्शन 'बी' को वापस करना है। लेकिन 'b' कुछ नहीं देता है, तो यह कथन 'return b ()' कुछ भी नहीं देता है। यदि b () एक संख्या वापस करते हैं, तो 'return b ()' एक संख्या भी है।

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


स्निपेट दो

function a() {
  
    alert('A!');

    function b(){
        alert('B!'); 
    }

    return b; //return pointer to function b here
}

var s = a();  //s get the value of pointer to b
alert('break');
s(); // b() function is executed

अब, फ़ंक्शन 'a' पॉइंटर / उर्फ ​​को 'b' नामक फ़ंक्शन पर लौटाता है। इसलिए जब 's = a ()' निष्पादित होता है, तो 's' को b की ओर इशारा करते हुए एक मान मिलेगा, यानी 's' अब 'b' का एक उपनाम है, जो 'b' के बराबर कॉलिंग है। यानी 's' अब एक फंक्शन है। एक्सक्यूट '()' का अर्थ है फंक्शन 'बी' को चलाने के लिए ('बी' को निष्पादित करने के समान), 'बी!' दिखाने वाला एक डायलॉग बॉक्स। दिखाई देगा (यानी 'अलर्ट' ('बी!'), फ़ंक्शन 'बी' में स्टेटमेंट)


-2

यह वास्तविक जीवन में सुपर उपयोगी है।

Express.js के साथ काम करना

तो आपका नियमित expressमार्ग इस तरह दिखता है:

function itWorksHandler( req, res, next ) {
  res.send("It works!");
}

router.get("/check/works", itWorksHandler );

लेकिन क्या होगा अगर आपको कुछ रैपर, त्रुटि हैंडलर या एसएमएस जोड़ने की आवश्यकता है?

फिर आप एक आवरण से अपने कार्य को आमंत्रित करते हैं।

function loggingWrapper( req, res, next, yourFunction ) {
  try {
    yourFunction( req, res );
  } catch ( err ) {
    console.error( err );
    next( err );
  }
}

router.get("/check/works", function( req, res, next ) {
  loggingWrapper( req, res, next, itWorksHandler );
});

जटिल लगता है? खैर, यह कैसे के बारे में:

function function loggingWrapper( yourFunction ) => ( req, res, next ) {
  try {
    yourFunction( req, res, next );
  } catch ( err ) {
    console.error( err );
    next( err );
  }
}

router.get("/check/works", loggingWrapper( itWorksHandler ) );

अंत में देखें कि आप एक फ़ंक्शन loggingWrapperको किसी अन्य फ़ंक्शन के रूप में एक तर्क दे रहे हैं itWorksHandler, और आपका loggingWrapperएक नया फ़ंक्शन देता है जो req, res, nextतर्क के रूप में लेता है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.