जावास्क्रिप्ट में परिभाषित होने से पहले मैं एक फ़ंक्शन का उपयोग क्यों कर सकता हूं?


168

यह कोड हमेशा अलग-अलग ब्राउज़रों में भी काम करता है:

function fooCheck() {
  alert(internalFoo()); // We are using internalFoo() here...

  return internalFoo(); // And here, even though it has not been defined...

  function internalFoo() { return true; } //...until here!
}

fooCheck();

मुझे एक भी संदर्भ नहीं मिला कि यह क्यों काम करना चाहिए, हालांकि। मैंने इसे पहली बार जॉन रेजिग के प्रेजेंटेशन नोट में देखा था, लेकिन यह केवल उल्लेख किया गया था। वहाँ या उस मामले के लिए कहीं भी कोई स्पष्टीकरण नहीं है।

क्या कोई मुझे खुश कर सकता है?


3
फ़ायरफ़ॉक्स के नए संस्करणों में, यह काम नहीं करता है यदि कोड एक कोशिश / पकड़ में है। इस फिडेल को देखें: jsfiddle.net/qzzc1evt
जोशुआ स्मिथ

जवाबों:


217

functionघोषणा जादू है और कारण बनता है इसके पहचानकर्ता अपने कोड ब्लॉक * निष्पादित किया जाता है में कुछ भी करने से पहले बाध्य होने के लिए।

यह एक functionअभिव्यक्ति के साथ असाइनमेंट से भिन्न होता है , जिसका मूल्यांकन सामान्य टॉप-डाउन ऑर्डर में किया जाता है।

यदि आपने कहने के लिए उदाहरण बदल दिया है:

var internalFoo = function() { return true; };

यह काम करना बंद कर देगा।

फ़ंक्शन की घोषणा वाक्यविन्यास फ़ंक्शन के अभिव्यक्ति से काफी अलग है, भले ही वे लगभग समान दिखते हैं और कुछ मामलों में अस्पष्ट हो सकते हैं।

यह ECMAScript मानक , खंड 10.1.3 में प्रलेखित है । दुर्भाग्य से ECMA-262 मानकों-मानकों द्वारा भी बहुत पठनीय दस्तावेज नहीं है!

*: युक्त समारोह, ब्लॉक, मॉड्यूल या स्क्रिप्ट।


मुझे लगता है कि यह वास्तव में पठनीय नहीं है। मैंने सिर्फ उस अनुभाग को पढ़ा है जिसे आपने 10.1.3 बताया था और यह नहीं पाया कि वहाँ के प्रावधान इस व्यवहार का कारण क्यों बनेंगे। जानकारी के लिए धन्यवाद।
एडू फेलिप

2
@bobince ठीक है, मुझे खुद पर संदेह होने लगा जब मुझे इस पृष्ठ पर "उत्थापन" शब्द का एक भी उल्लेख नहीं मिला। उम्मीद है कि इन टिप्पणियों में चीजों को सही सेट करने के लिए पर्याप्त Google जूस ™ है :)
मैथियास ब्यनेंस

2
यह एक लोकप्रिय प्रश्न / उत्तर कॉम्बो है। ES5 एनोटेट विनिर्देश के लिंक / अंश के साथ अद्यतन करने पर विचार करें। (जो थोड़ा अधिक सुलभ है।)


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

28

इसे परिभाषित करने से पहले इसे HOISTING - इन्वोकेशन (कॉलिंग) कहा जाता है।

दो अलग-अलग प्रकार के फ़ंक्शन, जिनके बारे में मैं लिखना चाहता हूं:

अभिव्यक्ति कार्य और घोषणा कार्य

  1. अभिव्यक्ति के कार्य:

    फ़ंक्शन अभिव्यक्तियों को एक चर में संग्रहीत किया जा सकता है ताकि उन्हें फ़ंक्शन नामों की आवश्यकता न हो। उन्हें एक अनाम फ़ंक्शन (नाम के बिना एक फ़ंक्शन) के रूप में भी नामित किया जाएगा।

    इन कार्यों को आह्वान करने के लिए उन्हें हमेशा एक चर नाम की आवश्यकता होती है । इस प्रकार का कार्य तब नहीं होगा जब इसे परिभाषित करने से पहले कहा जाता है जिसका अर्थ है कि उत्थापन यहाँ नहीं हो रहा है। हमें हमेशा पहले अभिव्यक्ति फ़ंक्शन को परिभाषित करना होगा और फिर इसे लागू करना होगा।

    let lastName = function (family) {
     console.log("My last name is " + family);
    };
    let x = lastName("Lopez");

    इसे आप ECMAScript 6 में लिख सकते हैं:

    lastName = (family) => console.log("My last name is " + family);
    
    x = lastName("Lopez");
  2. घोषणा कार्य:

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

    function Name(name) {
      console.log("My cat's name is " + name);
    }
    Name("Chloe");

    उत्थापन का उदाहरण:

    Name("Chloe");
    function Name(name) {
       console.log("My cat's name is " + name);
    }

let fun = theFunction; fun(); function theFunction() {}भी काम करेंगे (नोड और ब्राउज़र्स)
9

14

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

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

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

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

संशोधन: स्वीकृत उत्तर (ऊपर) की पुष्टि करने के लिए, फायरबग का उपयोग एक वेब पेज के स्क्रिप्ट सेक्शन को करने के लिए करें। आप देखेंगे कि यह फंक्शन से फ़ंक्शन तक छोड़ सकता है, केवल पहली पंक्ति पर जाकर, इससे पहले कि यह वास्तव में किसी भी कोड को निष्पादित करता है।


3

कुछ भाषाओं की आवश्यकता है कि पहचानकर्ताओं को उपयोग करने से पहले परिभाषित किया जाना चाहिए। इसका एक कारण यह है कि कंपाइलर सोर्सकोड पर सिंगल पास का उपयोग करता है।

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


2

मैंने केवल जावास्क्रिप्ट का उपयोग किया है। मुझे यकीन नहीं है कि यह मदद करेगा, लेकिन यह बहुत ही समान है जो आप के बारे में बात कर रहे हैं और कुछ अंतर्दृष्टि दे सकते हैं:

http://www.dustindiaz.com/javascript-function-declaration-ambiguity/


लिंक अब मृत नहीं है।
mwclarke

1
लिंक मर चुका है।
जेरोम इंडिफेंजो

यहां आर्काइव.ऑर्ग से एक स्नैपशॉट दिया गया है। लगता है कि लेखक ने पुरानी सामग्री के लिए अपनी पूरी वेबसाइट को नीचे ले लिया , न कि यह ब्लॉग पोस्ट उस श्रेणी में आती है।
jkmartindale

1

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

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


-4

उसी कारण से निम्नलिखित हमेशा fooवैश्विक नामस्थान में रखा जाएगा :

if (test condition) {
    var foo;
}

8
दरअसल, यह बहुत अलग कारणों से है। ifब्लॉक, एक गुंजाइश नहीं बना थोड़ी देर करता function()ब्लॉक हमेशा एक बनाता है। वास्तविक कारण यह था कि वैश्विक जावास्क्रिप्ट नामों की परिभाषा संकलन चरण में होती है, ताकि कोड न चलने पर भी नाम परिभाषित हो। (क्षमा करें, यह टिप्पणी करने में इतना समय लगा)
एडू फेलिप
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.