2010-11-01 10 views
32

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

यह प्रदर्शित करता है "हैलो दुनिया":

hello(); 
function hello() { alert("Hello world"); } 

लेकिन यह प्रदर्शित करता है "ReferenceError: हैलो परिभाषित नहीं है":

try { 
    hello(); 
    function hello() { alert("Hello world"); } 
} catch (err) { 
    alert(err); 
} 

तो वहाँ स्पष्ट रूप से कुछ "विशेष" के साथ एक कोशिश ब्लॉक के बारे में है समारोह घोषणाओं का सम्मान। क्या इस व्यवहार को दूर करने का कोई तरीका है?

+1

यह ब्राउज़र किस में है? –

+0

सहमत; यह काम नहीं करता (फ़ायरफ़ॉक्स), लेकिन सवाल मैं पूछूंगा कि आपको इसकी आवश्यकता क्यों है? कोशिश/पकड़ ब्लॉक के अंदर आपको फ़ंक्शन घोषणाएं क्यों करने की आवश्यकता है? – Spudley

+1

फ़ायरफ़ॉक्स। अब मैं देखता हूं कि आईई और क्रोम दोनों हेलो दुनिया को प्रदर्शित करते हैं ... –

उत्तर

5

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

यह Firefox, IE, क्रोम में काम करता है:

try { 
    (function(){ 
    hello(); 
    function hello() { alert("Hello world"); } 
    }()) 
} catch (err) { 
    alert(err); 
} 
पाठ्यक्रम कार्य करता है और चर कोशिश समारोह में परिभाषित के

नहीं, पकड़ ब्लॉक में लंबे समय तक दिखाई दे रहे हैं के रूप में वे तत्काल समारोह आवरण के बिना होगा। लेकिन यह कोशिश/पकड़ स्क्रिप्ट रैपिंग के लिए एक संभावित कामकाज है।

26

फ़ायरफ़ॉक्स फ़ंक्शन स्टेटमेंट को अलग-अलग व्याख्या करता है और स्पष्ट रूप से उन्होंने फ़ंक्शन घोषणा के लिए घोषणापत्र को तोड़ दिया। (A good read about named functions/declaration vs expression)

क्यों फ़ायरफ़ॉक्स बयान की व्याख्या करता है अलग ढंग से निम्न कोड की वजह से है:

if (true) { 
    function test(){alert("YAY");} 
} else { 
    function test(){alert("FAIL");} 
} 
test(); // should alert FAIL 

घोषणा उत्थापन के कारण, समारोह test चाहिए हमेशा सतर्क "असफल", लेकिन नहीं फ़ायरफ़ॉक्स में। उपर्युक्त कोड वास्तव में फ़ायरफ़ॉक्स में "यय" को अलर्ट करता है और मुझे उस कोड पर संदेह है जो अंततः घोषणापत्र को पूरी तरह से तोड़ देता है।

मुझे लगता है कि फ़ायरफ़ॉक्स विभिन्न घोषणाओं में फ़ंक्शन घोषणाएं बदलता है जब वे/अन्य में स्थित होते हैं या कथन/प्रयास करते हैं। इसलिए जैसा:

// firefox interpretted code 
var test; // hoisted 
if (true) { 
    test = function(){alert("yay")} 
} else { 
    test = function(){alert("fail")} 
} 

Šime Vidas के साथ एक संक्षिप्त बहस के बाद, मैं कहना है कि समारोह घोषणाओं के साथ Firefox के व्यवहार की वजह से, गैर मानक है:

The production SourceElement : Statement is processed for function declarations by taking no action.
The production SourceElement : Statement is evaluated as follows:

  1. Evaluate Statement.
  2. Return Result(1).

दोनों FunctionDeclaration और वक्तव्य SourceElements कर रहे हैं, ergo, एक बयान के अंदर कोई समारोह घोषणा नहीं होनी चाहिए (अगर/अन्य, कोशिश/पकड़)। Šime Vidas एक brownie दे दो!

कोशिश/पकड़ मूल रूप से अन्य रूपों का एक और रूप है और शायद उसी अपवाद कोड का उपयोग करता है।

+0

@BGerrissen "या तो रास्ता मानक है" से आपका क्या मतलब है? फ़ंक्शन स्टेटमेंट आधिकारिक ईसीएमएस्क्रिप्ट मानक का हिस्सा नहीं हैं। वे कुछ ऐसा हैं जो मोज़िला ने पेश किया था। –

+0

@ सेम http://bclary.com/2004/11/07/#a-13 (घोषणा) पहले उल्लिखित विकल्प कहीं भी है, लेकिन एटीएम खोजने के लिए बहुत अस्पष्ट है। मैंने इसे कुछ समय पहले पाया है ... – BGerrissen

+0

स्टेटमेंट, घोषणा, एक चुनें;) – BGerrissen

1

आप इसे इस तरह से हमेशा कर सकते हैं और दोनों दुनिया का सबसे अच्छा मिलता है:

function hello() { 
    alert("Hello world"); 
} 

try { 
    hello(); 
} 
catch (err) { 
    alert(err); 
} 

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

संपादित करें:

प्रदर्शित करने के लिए है कि इस बस के रूप में एक कोशिश पकड़ में पूरे कोड घेर के रूप में टिकाऊ है, मैं एक अधिक विस्तृत उदाहरण प्रदान कर रहा हूँ।

function hello(str) { 
    alert("Hello, " + str); 
} 

function greet() { 
    asdf 
} 

try { 
    var user = "Bob"; 
    hello(user); 
    greet(); 
    asdf 
} 
catch (e) { 
    alert(e); 
} 

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

मुझे लगता है कि यह एक शैली वरीयता है, लेकिन ऐसा लगता है कि यह अन्य विकल्पों की तुलना में मेरे लिए अधिक पठनीय और रखरखाव योग्य है।

+0

यह स्क्रिप्ट-लोड-टाइम त्रुटियों को नहीं पकड़ पाएगा। जब तक आप पूरे स्क्रिप्ट बॉडी को हैलो() फ़ंक्शन में ले जाने का मतलब नहीं रखते हैं, और तब हमारे पास ट्राई-फ़ंक्शन रैपर दृष्टिकोण जैसा ही होता है। –

+0

लोड-टाइम त्रुटि से आपका क्या मतलब है? यदि आप फ़ंक्शन परिभाषा के अंदर कोई अपरिभाषित संदर्भ डालते हैं, तो यह अपेक्षा के अनुसार काम करेगा। यह केवल प्रारंभिक लोड पर फ़ंक्शन का नाम जांचता है, और जब कॉल को ट्राइक-कैच द्वारा नियंत्रित अपवाद उत्पन्न करता है। – sworoc

+0

उदाहरण के लिए, गलती से फ़ंक्शन और प्रयास के बीच की रेखा पर एक कचरा चरित्र टाइप करें। –

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

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