यह न तो स्कोप की समस्या है और न ही बंद होने की समस्या है। समस्या घोषणाओं और अभिव्यक्तियों के बीच की समझ में है ।
जावास्क्रिप्ट कोड, चूंकि नेटस्केप के पहले संस्करण में भी जावास्क्रिप्ट और माइक्रोसॉफ्ट की पहली प्रति है, इसे दो चरणों में संसाधित किया गया है:
चरण 1: संकलन - इस चरण में कोड को एक सिंटैक्स ट्री (और इंजन के आधार पर बाइटकोड या बाइनरी) में संकलित किया जाता है।
चरण 2: निष्पादन - पार्स कोड की व्याख्या तब की जाती है।
फ़ंक्शन घोषणा के लिए सिंटैक्स है:
function name (arguments) {code}
तर्क निश्चित रूप से वैकल्पिक हैं (कोड वैकल्पिक भी है लेकिन इसका क्या मतलब है?)।
लेकिन जावास्क्रिप्ट भी आपको अभिव्यक्ति का उपयोग करके फ़ंक्शन बनाने की अनुमति देता है । फ़ंक्शन अभिव्यक्तियों के लिए सिंटैक्स फ़ंक्शन घोषणाओं के समान हैं सिवाय इसके कि वे अभिव्यक्ति के संदर्भ में लिखे गए हैं। और भाव हैं:
=
संकेत के अधिकार के लिए कुछ भी (या :
वस्तु शाब्दिक पर)।
- कोष्ठकों में कुछ भी
()
।
- कार्यों के लिए पैरामीटर (यह वास्तव में पहले से ही 2 द्वारा कवर किया गया है)।
घोषणाओं के विपरीत अभिव्यक्तियों को संकलन चरण के बजाय निष्पादन चरण में संसाधित किया जाता है। और इस वजह से भावों का क्रम मायने रखता है।
तो, स्पष्ट करने के लिए:
(function() {
setTimeout(someFunction, 10);
var someFunction = function() { alert('here1'); };
})();
चरण 1: संकलन। संकलक देखता है कि चर someFunction
परिभाषित किया गया है इसलिए यह इसे बनाता है। डिफ़ॉल्ट रूप से बनाए गए सभी चरों में अपरिभाषित का मान होता है। ध्यान दें कि कंपाइलर इस बिंदु पर अभी तक मान निर्दिष्ट नहीं कर सकता है क्योंकि मानों को असाइन करने के लिए कुछ कोड को निष्पादित करने के लिए दुभाषिया की आवश्यकता हो सकती है ताकि असाइन करने के लिए मान प्रदान किया जा सके। और इस स्तर पर हम अभी तक कोड निष्पादित नहीं कर रहे हैं।
चरण 2: निष्पादन। दुभाषिया देखता है कि आप चर someFunction
को सेटटाइमआउट में पास करना चाहते हैं । और इसलिए यह करता है। दुर्भाग्य से वर्तमान मूल्य someFunction
अपरिभाषित है।
(function() {
setTimeout(someFunction, 10);
function someFunction() { alert('here2'); }
})();
चरण 1: संकलन। संकलक देखता है कि आप someFunction नाम के साथ एक फ़ंक्शन घोषित कर रहे हैं और इसलिए यह इसे बनाता है।
चरण 2: दुभाषिया देखता है कि आप someFunction
सेटटाइमआउट में पास होना चाहते हैं । और इसलिए यह करता है। वर्तमान मूल्य someFunction
इसका संकलित फ़ंक्शन घोषणा है।
(function() {
setTimeout(function() { someFunction(); }, 10);
var someFunction = function() { alert('here3'); };
})();
चरण 1: संकलन। संकलक देखता है कि आपने एक चर घोषित किया है someFunction
और इसे बनाता है। पहले की तरह, इसका मूल्य अपरिभाषित है।
चरण 2: निष्पादन। दुभाषिया एक अनाम फ़ंक्शन को बाद में निष्पादित करने के लिए सेटटाइमआउट करता है। इस फ़ंक्शन में यह देखता है कि आप वेरिएबल का उपयोग कर रहे हैं, someFunction
इसलिए यह वेरिएबल को बंद कर देता है। इस बिंदु पर मूल्य someFunction
अभी भी अपरिभाषित है। फिर यह देखता है कि आप किसको एक कार्य सौंप रहे हैं someFunction
। इस बिंदु पर का मान someFunction
अब अपरिभाषित नहीं है। एक सेकंड के 1/100 वें बाद में सेटटाइमआउट ट्रिगर हो जाता है और someFunction कहा जाता है। चूंकि इसका मूल्य अब अपरिभाषित नहीं है।
केस 4 वास्तव में केस 2 का एक और संस्करण है, जिसमें थोडा थोडा 3 केस फेंका गया है। बिंदु someFunction
पर सेटटाइमआउट करने के लिए इसे पहले से मौजूद होने के कारण पास किया गया है।
अतिरिक्त स्पष्टीकरण:
आप आश्चर्यचकित हो सकते हैं कि setTimeout(someFunction, 10)
someFunction की स्थानीय प्रति और सेटटाइमआउट के लिए पारित होने के बीच कोई संबंध क्यों नहीं बनता है। इसका उत्तर यह है कि जावास्क्रिप्ट में फ़ंक्शन तर्क हमेशा होते हैं, हमेशा मान से पारित किए जाते हैं यदि वे संख्या या तार हैं या हर चीज के लिए संदर्भ द्वारा। इसलिए सेटटाइमआउट वास्तव में वैरिएबल को प्राप्त नहीं होता है, जो इसके पास जाता है (जिसका मतलब होता है कि एक क्लोजर बनाया जा रहा है), लेकिन केवल उस वस्तु को प्राप्त होता है जिसे someFunction संदर्भित करता है (जो इस मामले में एक फ़ंक्शन है)। यह ब्रेकिंग क्लोजर (उदाहरण के लिए छोरों में) के लिए जावास्क्रिप्ट में सबसे व्यापक रूप से उपयोग किया जाने वाला तंत्र है।