2008-11-04 6 views
135

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

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

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

क्या कोई मुझे प्रबुद्ध कर सकता है?

+2

फ़ायरफ़ॉक्स के नए संस्करण में, यह अगर कोड आज़माएं/कैच में है काम नहीं करता। यह पहेली देखें: http://jsfiddle.net/qzzc1evt/ –

उत्तर

182

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

यह एक function अभिव्यक्ति है, जो सामान्य ऊपर से नीचे के क्रम में मूल्यांकन किया जाता है के साथ एक काम से अलग है।

आप कहने के लिए उदाहरण परिवर्तित हुआ है:

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

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

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

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

*: युक्त फ़ंक्शन, ब्लॉक, मॉड्यूल या स्क्रिप्ट।

+0

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

+24

इसे "hoisting" कहा जाता है, है ना? –

+0

@Mathias: सही। – bobince

2

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

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

+0

लिंक मर चुका है – Leonardo

+0

लिंक अब मर चुका नहीं है। – mwclarke

+0

लिंक मर चुका है। आपके उत्तर के अंत में संशोधन के लिए –

2

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

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

0

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

केवल बाद में, तो कोड चलता है, जावास्क्रिप्ट वास्तव में जानने के लिए कि "internalFoo" मौजूद है और यह क्या है और क्या यह कहा जा सकता है, आदि

13

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

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

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

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

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

+4

+1, जो आवश्यक हिस्सा है। – hippietrail

-4

इसी कारण निम्नलिखित हमेशा ग्लोबल नेम स्पेस में foo डाल देंगे के लिए:

if (test condition) { 
    var foo; 
} 
+8

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

4

यह उत्थापन कहा जाता है - आह्वान (कहा जाता है) जहां यह परिभाषित किया गया है से पहले एक समारोह। कार्यों की

दो अलग अलग प्रकार है कि मैं के बारे में लिखना चाहते हैं:

अभिव्यक्ति कार्य & मंदी कार्य

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

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

    आमंत्रित करने के लिए (0) उन्हें हमेशा परिवर्तनीय नाम का उपयोग करने की आवश्यकता है। इस प्रकार के फ़ंक्शन काम नहीं करेंगे अगर कॉल कहां से परिभाषित किया गया है जिसका मतलब है कि होस्टिंग यहां नहीं हो रहा है। हमें हमेशा पहले अभिव्यक्ति फ़ंक्शन को परिभाषित करना होगा और फिर उसे आमंत्रित करना होगा।

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

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

  • कोई संबंधित समस्या नहीं^_^