जावास्क्रिप्ट फ़ंक्शन ऑर्डर: यह क्यों मायने रखता है?


106

मूल प्रश्न:

JSHint शिकायत करता है जब मेरा जावास्क्रिप्ट एक फ़ंक्शन को कॉल करता है जो पृष्ठ को कॉल की तुलना में नीचे परिभाषित करता है। हालाँकि, मेरा पेज एक गेम के लिए है, और जब तक पूरी चीज डाउनलोड नहीं हो जाती, तब तक कोई फंक्शन नहीं किया जाता है। तो मेरे फंक्शन कोड में ऑर्डर फ़ंक्शंस क्यों दिखाई देते हैं?

संपादित करें: मुझे लगता है कि मुझे जवाब मिल गया होगा।

http://www.adequatelygood.com/2010/2/JavaScript-Scoping-and-Hoisting

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


अद्यतन में उत्कृष्ट संदर्भ के लिए +1। और मुझे आशा है कि आपको विश्वास दिलाता हूं कि आपको वास्तव में अपने कोड को फिर से ऑर्डर करने की आवश्यकता नहीं है। :)
awm

जवाबों:


294

tl; dr यदि आप सब कुछ लोड होने तक कुछ भी नहीं कह रहे हैं, तो आपको ठीक होना चाहिए।


संपादित करें: एक सिंहावलोकन जो भी कुछ ES6 घोषणाओं (को शामिल किया गया के लिए let, const): https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Scope_Cheatsheet

यह अजीब व्यवहार पर निर्भर करता है

  1. आप कार्यों को कैसे परिभाषित करते हैं और
  2. जब आप उन्हें बुलाते हैं।

यहाँ कुछ उदाहरण हैं।

bar(); //This won't throw an error
function bar() {}

foo(); //This will throw an error
var foo = function() {}
bar();
function bar() {
    foo(); //This will throw an error
}
var foo = function() {}
bar();
function bar() {
    foo(); //This _won't_ throw an error
}
function foo() {}
function bar() {
    foo(); //no error
}
var foo = function() {}
bar();

इसकी वजह है किसी चीज को फहराना !

फ़ंक्शन को परिभाषित करने के दो तरीके हैं: फ़ंक्शन घोषणा और फ़ंक्शन अभिव्यक्ति । अंतर कष्टप्रद और मिनट है, तो चलिए इसे थोड़ा गलत कहते हैं: यदि आप इसे पसंद कर रहे हैं function name() {}, तो यह एक घोषणा है , और जब आप इसे लिखते हैं var name = function() {}(या किसी अनाम फ़ंक्शन को किसी रिटर्न को सौंपा जाता है, जैसी चीजें), यह एक समारोह अभिव्यक्ति

सबसे पहले, आइए देखें कि चर कैसे संभाले जाते हैं:

var foo = 42;

//the interpreter turns it into this:
var foo;
foo = 42;

अब, फ़ंक्शन घोषणाओं को कैसे नियंत्रित किया जाता है:

var foo = 42;
function bar() {}

//turns into
var foo; //Insanity! It's now at the top
function bar() {}
foo = 42;

varबयान "फेंकता है" निर्माण की fooबहुत शीर्ष करने के लिए, लेकिन अभी तक यह करने के लिए मान असाइन नहीं करता है। फ़ंक्शन की घोषणा रेखा के बगल में आती है, और अंत में एक मान असाइन किया जाता है foo

और इस बारे में क्या?

bar();
var foo = 42;
function bar() {}
//=>
var foo;
function bar() {}
bar();
foo = 42;

केवल घोषणा की fooशीर्ष करने के लिए ले जाया जाता है। कॉल barकिए जाने के बाद ही असाइनमेंट आता है, जहां यह सभी उत्थापन से पहले था।

और अंत में, सहमति के लिए:

bar();
function bar() {}
//turns to
function bar() {}
bar();

अब, फ़ंक्शन अभिव्यक्तियों के बारे में क्या ?

var foo = function() {}
foo();
//=>
var foo;
foo = function() {}
foo();

बस नियमित रूप से चर की तरह, पहली fooहै घोषित दायरे से उच्चतम बिंदु पर है, तो यह एक मूल्य असाइन किया गया है।

आइए देखें कि दूसरा उदाहरण एक त्रुटि क्यों फेंकता है।

bar();
function bar() {
    foo();
}
var foo = function() {}
//=>
var foo;
function bar() {
    foo();
}
bar();
foo = function() {}

जैसा कि हमने पहले देखा है, केवल बनाने fooको फहराया जाता है, असाइनमेंट आता है जहां यह "मूल" (अन-होवर्ड) कोड में दिखाई देता है। जब barकहा जाता है, इससे पहले कि fooयह एक मूल्य सौंपा है, इसलिए foo === undefined। अब फंक्शन-बॉडी में bar, ऐसा लगता है जैसे आप कर रहे हैं undefined(), जो एक त्रुटि फेंकता है।


इसे खोदने के लिए क्षमा करें, लेकिन Array.prototype.someMethod = function () {} को ओवरलोड किया गया है? यदि मेरी स्क्रिप्ट के अंत में इस प्रकार की चीजें हैं, तो मुझे त्रुटियां होने लगती हैं।
एज

आप कैसे सुनिश्चित करते हैं कि सब कुछ लोड हो रहा है ? क्या कोई सामान्य अभ्यास है?
नवंबर को zwcloud

6

मुख्य कारण शायद यह है कि JSLint फाइल पर केवल एक पास करता है, इसलिए यह नहीं जानता कि आप इस तरह के फ़ंक्शन को परिभाषित करेंगे

यदि आपने फ़ंक्शन स्टेटमेंट का उपयोग किया है

function foo(){ ... }

वास्तव में, जहां आप फ़ंक्शन की घोषणा करते हैं, वहां वास्तव में कोई अंतर नहीं है (यह हमेशा ऐसा व्यवहार करता है जैसे कि घोषणा शुरुआत में है)।

दूसरी ओर, यदि आपका फ़ंक्शन एक नियमित चर की तरह सेट किया गया था

var foo = function() { ... };

आपको गारंटी है कि आपको इसे इनिशियलाइज़ेशन से पहले कॉल करना होगा (यह वास्तव में बग्स का स्रोत हो सकता है)।


चूँकि टन के पुन: व्यवस्थित करना जटिल है और अपने आप में बग का एक स्रोत हो सकता है, मैं आपको एक समाधान के लिए खोज करने का सुझाव दूंगा। मुझे पूरा यकीन है कि आप JSLint को पहले से ही वैश्विक चर का नाम बता सकते हैं ताकि यह अघोषित सामान के बारे में शिकायत न करे।

फ़ाइल के beggining पर एक टिप्पणी रखो

/*globals foo1 foo2 foo3*/

या फिर आप इसके लिए एक टेक्स्ट बॉक्स का उपयोग कर सकते हैं। (मुझे भी लगता है कि आप इसे आंतरिक jslint फ़ंक्शन के तर्कों पर पारित कर सकते हैं यदि आप इसके साथ मध्यस्थता कर सकते हैं)।


धन्यवाद। तो / * ग्लोबल्स * / लाइन काम करेगा? अच्छा - मुझे पसंद करने के लिए JsHint पाने के लिए कुछ भी। मैं अभी भी जावास्क्रिप्ट में नया हूं और जब मैं एक पेज को रिफ्रेश करता हूं तो मुझे अकथनीय ठहराव मिलता है, फिर भी कोई भी बग नहीं आता है। इसलिए मुझे लगा कि समाधान सभी नियमों से खेलना है और फिर देखें कि क्या यह अभी भी होता है।
क्रिस टॉल्वर्टी

4

जावास्क्रिप्ट लिखने के तरीके के बारे में कई लोगों के मनमाने नियम हैं। ज्यादातर नियम बिलकुल बकवास हैं।

फंक्शन उत्थापन जावास्क्रिप्ट में एक विशेषता है क्योंकि यह एक अच्छा विचार है।

जब आपके पास एक आंतरिक फ़ंक्शन होता है जो अक्सर आंतरिक कार्यों की उपयोगिता होती है, तो इसे बाहरी फ़ंक्शन की शुरुआत में जोड़ना कोड लिखने की एक स्वीकार्य शैली है, लेकिन इसका दोष यह है कि आपको विवरण के माध्यम से पढ़ना है कि क्या प्राप्त करने के लिए बाहरी कार्य करता है।

आपको अपने कोडबेस में एक सिद्धांत पर टिकना चाहिए या तो अपने मॉड्यूल या फ़ंक्शन में पहले या आखिरी में निजी फ़ंक्शन डालें। JSHint स्थिरता को लागू करने के लिए अच्छा है, लेकिन आपको अपनी आवश्यकताओं को पूरा करने के लिए ABSOLUTELY को समायोजित करना चाहिए .jshintrc, अन्य लोगों को निराला कोडिंग अवधारणाओं के लिए अपने स्रोत कोड को समायोजित न करें।

एक कोडिंग शैली जिसे आप जंगली में देख सकते हैं, जिससे आपको बचना चाहिए क्योंकि इससे आपको कोई लाभ नहीं होता है और केवल दर्द निवारण संभव है:

function bigProcess() {
    var step1,step2;
    step1();
    step2();

    step1 = function() {...};
    step2 = function() {...};
}

यह वही है जिससे बचने के लिए फंक्शन फहराना है। बस भाषा सीखें और उसकी ताकत का फायदा उठाएं।


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