यह जावास्क्रिप्ट / jQuery सिंटैक्स कैसे काम करता है: (फ़ंक्शन (विंडो, अपरिभाषित) {}) (विंडो)?


153

क्या आपने कभी jQuery 1.4 स्रोत कोड पर हुड के नीचे एक नज़र डाला और देखा कि यह निम्नलिखित तरीके से कैसे समझाया जाता है:

(function( window, undefined ) {

  //All the JQuery code here 
  ...

})(window);

मैंने जावास्क्रिप्ट नेमस्पेसिंग पर एक लेख पढ़ा है और एक अन्य जिसे " एक महत्वपूर्ण जोड़ी का परेंस " कहा जाता है , इसलिए मुझे कुछ पता है कि यहाँ क्या हो रहा है।

लेकिन मैंने इस विशेष वाक्य विन्यास को पहले कभी नहीं देखा है। undefinedवह वहां क्या कर रहा है? और windowइसे पारित करने की आवश्यकता क्यों है और फिर अंत में फिर से दिखाई देगा?


3
मैं जोड़ना चाहता था कि पॉल आयरिश इस वीडियो में इस बारे में बात करता है: paulirish.com/2010/10-things-i-learned-from-the-jquery-source
Mottie

@ बर्गी ने आपने मेरे प्रश्न को दूसरे के डुप्लिकेट के रूप में चिह्नित किया था लेकिन मैंने डुप्लिकेट से लगभग एक साल पहले प्रश्न पूछा था। कलाकारों को दूसरे तरीके से घूमना चाहिए।
dkinzer

@dkinzer: यह पहले से पूछे जाने के बारे में नहीं है, यह उच्चतम-गुणवत्ता वाले उत्तर के बारे में है। बेशक, इस मामले में यह गर्दन और गर्दन है, लेकिन मुझे सबसे अच्छा होने के लिए सीएमएस का जवाब मिला। इसके बारे में चर्चा करने के लिए chat.stackoverflow.com/rooms/17 पर आइए , हालांकि
Bergi

जवाबों:


161

अपरिभाषित एक सामान्य चर है और बस के साथ बदला जा सकता है undefined = "new value";। तो jQuery एक स्थानीय "अपरिभाषित" चर बनाता है जो वास्तव में अपरिभाषित है।

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


1
धन्यवाद! यह एक बहुत जानकारीपूर्ण वीडियो था। मुझे लगता है कि आपको "विंडो वेरिएबल को लोकल बनाया गया है" कहने के लिए अपनी प्रतिक्रिया संपादित करने की आवश्यकता है। मुझे लगता है कि यह सबसे अच्छा जवाब है। मैंने गिना और पाया कि विंडो ऑब्जेक्ट JQuery स्रोत कोड में कम से कम 17 बार कहा जाता है। इसलिए विंडो को लोकल स्कोप में ले जाने में महत्वपूर्ण प्रभाव पड़ता है।
dkinzer

@DKinzer ओह हाँ, आप कठोर हैं, बेशक यह स्थानीय बना है। खुशी है कि मैं आपकी मदद कर सका =)
विंसेंट

1
इस अद्यतन परीक्षण के अनुसार jsperf.com/short-scope/5 पासिंग 'विंडो' वास्तव में धीमी है, जब यह jQuery के माध्यम से एक खिड़की को स्थिर करने के लिए आता है, और विशेष रूप से सफारी के लिए बुरा है। इसलिए जब 'अपरिभाषित' का उपयोग मामला होता है, तो मुझे पूरा यकीन नहीं है कि 'विंडो' सभी मामलों में विशेष रूप से उपयोगी है।
हेक्सालिस

1
यह कोड को छोटा करने के लिए एक सकारात्मक प्रभाव भी है। तो "विंडो" और "अपरिभाषित" के हर उपयोग को मिनिज़र द्वारा छोटे नाम से बदला जा सकता है।
टिलिंडिग

2
@ lukas.pukenis जब आप एक पुस्तकालय बना रहे हैं जो लाखों वेबसाइटों में उपयोग किया जाता है, तो यह समझदारी है कि पागल लोग क्या करेंगे, इसके बारे में धारणा नहीं बनाते हैं।
JLRishe

54

अपरिभाषित

undefinedएक तर्क के रूप में घोषित करके लेकिन इसे कभी भी एक मूल्य के रूप में पारित करने से यह सुनिश्चित नहीं होता है कि यह हमेशा अपरिभाषित है, क्योंकि यह वैश्विक दायरे में केवल एक चर है जिसे अधिलेखित किया जा सकता है। यह a === undefinedएक सुरक्षित विकल्प बनाता है typeof a == 'undefined', जो कुछ पात्रों को बचाता है। यह कोड को और अधिक अनुकूल बनाता है, क्योंकि उदाहरण के लिए undefinedइसे छोटा किया जा सकता है u, जिससे कुछ और पात्रों को बचाया जा सकता है ।

खिड़की

पासिंग window: एक तर्क के रूप स्थानीय गुंजाइश है, जो प्रदर्शन को प्रभावित करता में प्रति भी रखता है http://jsperf.com/short-scopewindowअब सभी पहुंचों को गुंजाइश श्रृंखला तक एक स्तर कम यात्रा करनी होगी। जैसा कि undefined, एक स्थानीय प्रतिलिपि फिर से और अधिक आक्रामक minification के लिए अनुमति देता है।


पक्षीय लेख:

हालाँकि यह jQuery डेवलपर्स का इरादा नहीं रहा हो सकता है, windowलाइब्रेरी को सर्वर-साइड जावास्क्रिप्ट वातावरण में अधिक आसानी से एकीकृत करने की अनुमति देता है, उदाहरण के लिए नोड.जेएस - जहां कोई वैश्विक windowवस्तु नहीं है। ऐसी स्थिति में, windowऑब्जेक्ट को किसी दूसरे के साथ बदलने के लिए केवल एक लाइन को बदलना होगा । JQuery के मामले में, windowHTML स्क्रैपिंग के उद्देश्य से एक मॉक ऑब्जेक्ट बनाया और पारित किया जा सकता है (एक पुस्तकालय जैसे कि jsdom ऐसा कर सकता है)।


2
+1 मिनिफिकेशन का उल्लेख करने के लिए, मैं चाहता हूं कि मैं jsperf के लिए +2 - minified संस्करण है (function(a,b){})(window);- aऔर bसे बहुत छोटे हैं windowऔर undefined:)
gnarf

+1 मैंने पहले स्कोप चेन के बारे में सुना था , लेकिन यह शब्द भूल गए। धन्यवाद!
एलेक्स

यह शून्य (0) का उपयोग करने का एक विकल्प भी है जो एक ही कारण के लिए था: शून्य (0) अपरिभाषित मूल्य प्राप्त करने का एक सुरक्षित तरीका है।
glmxndr

"क्या आप कहते हैं कि" यह अन्य प्रश्न के संदर्भ में है: stackoverflow.com/questions/4945265/...
gnarf

@gnarf, अधिसूचना के लिए धन्यवाद कि प्रश्नों को मिला दिया गया था। मैं अपने उत्तर को थोड़ा और समझ बनाने के लिए संपादित करूंगा;)
डेविड तांग

16

दूसरों ने समझाया है undefinedundefinedएक वैश्विक चर की तरह है जिसे किसी भी मूल्य पर पुनर्परिभाषित किया जा सकता है। यह तकनीक सभी अपरिभाषित चेक को तोड़ने से रोकने के लिए है यदि कोई कहता है, undefined = 10कहीं। एक तर्क जो कभी पारित नहीं होता undefinedहै वह चर के मूल्य के बावजूद वास्तविक होने की गारंटी देता है undefined

विंडो पास करने का कारण निम्नलिखित उदाहरण से स्पष्ट किया जा सकता है।

(function() {
   console.log(window);
   ...
   ...
   ...
   var window = 10;
})();

कंसोल क्या लॉग करता है? windowवस्तु का मूल्य सही है? गलत! 10? गलत! यह लॉग करता है undefined। जावास्क्रिप्ट दुभाषिया (या JIT संकलक) इसे इस तरह से फिर से लिखता है -

(function() {
   var window; //and every other var in this function

   console.log(window);
   ...
   ...
   ...
   window = 10;

})();

हालाँकि, यदि आप windowचर को तर्क के रूप में लेते हैं, तो कोई संस्करण नहीं है और इसलिए कोई आश्चर्य नहीं है।

मुझे नहीं पता कि jQuery यह कर रहा है या नहीं, लेकिन यदि आप windowकिसी भी कारण से अपने फ़ंक्शन में कहीं भी स्थानीय चर को पुनर्परिभाषित कर रहे हैं , तो इसे वैश्विक दायरे से उधार लेना एक अच्छा विचार है।


6

windowइस तरह से पारित किया जाता है कि जैसे ही किसी ने IE में विंडो ऑब्जेक्ट को फिर से परिभाषित करने का फैसला किया है, मैं उसी के लिए मान लेता हूं undefined, यदि इसे बाद में किसी तरह से फिर से सौंपा गया हो।

windowउस स्क्रिप्ट में शीर्ष केवल "विंडो" तर्क को नाम दे रहा है, एक तर्क जो अधिक स्थानीय है जो वैश्विक windowसंदर्भ है और यह इस बंद के अंदर कोड का उपयोग करेगा। windowअंत में वास्तव में क्या इस मामले में वर्तमान अर्थ पहला तर्क के लिए पारित करने के लिए, की निर्दिष्ट करने है window... आशा आप बँधा हुआ नहीं किया है windowइससे पहले कि ऐसा होता है।

यह jQuery, प्लगइन .noConflict()हैंडलिंग में उपयोग किए जाने वाले सबसे विशिष्ट मामले को दिखाते हुए सोचने में आसान हो सकता है , इसलिए कोड के बहुमत के लिए आप अभी भी उपयोग कर सकते हैं $, भले ही इसका मतलब है कि इस दायरे के बाहर कुछ और हो।jQuery

(function($) {
  //inside here, $ == jQuery, it was passed as the first argument
})(jQuery);

धन्यवाद। इसके बहुत सारे अर्थ निकलते हैं। हालाँकि, मुझे लगता है कि उत्तर इस का एक संयोजन है और @ सी। ज़ाका कहते हैं।
dkinzer

@DKinzer मुझे डर है कि मैं सी। ज़कस नहीं हूँ;)
विंसेंट

@ विंसेंट, उस के बारे में खेद :-)
डिकंजेकर

5

1000000 पुनरावृत्तियों के साथ परीक्षण किया गया। इस तरह के स्थानीयकरण का प्रदर्शन में कोई प्रभाव नहीं था। 1000000 पुनरावृत्तियों में एक भी मिलीसेकंड नहीं। यह बस बेकार है।


2
उल्लेख नहीं करने के लिए, क्लोजर फ़ंक्शन के उदाहरण के साथ सभी चर को वहन करता है, इसलिए यदि आपके पास बंद होने में 100 बाइट्स हैं, और 1000 इंस्टेंस हैं जो अधिक मेमोरी का 100kb है।
आकाश काव

@ आकाश और @ सेमरा, मुझे नहीं लगता कि यह परीक्षण वास्तव में इस बात का कारण है कि आप वास्तविक दुनिया की स्थिति में खिड़की से क्यों गुजरेंगे। प्रदर्शन लाभ केवल तभी देखने को मिलता है जब आपके पास गहरी नेस्टेड क्लोजर होते हैं जो उस वैरिएबल को स्कोप चेन के साथ एक्सेस करते हैं। जाहिर है कि अगर आपका फंक्शन वेरिएबल से स्कोप चेन पर केवल एक कदम दूर है, तो आपको ज्यादा फायदा नहीं होगा। लेकिन अगर यह वहाँ नीचे waaaay था और windowआप एक स्थानीय प्रतिलिपि द्वारा कुछ लाभ देखने के लिए प्राप्त करने की आवश्यकता हो सकती है।
21

@gabereal नए जावास्क्रिप्ट इंजन संकलन के समय क्लोजर को हल करते हैं, रनटाइम पर क्लोजर में कोई प्रदर्शन लाभ नहीं है। मुझे संदेह है कि कोई औसत दर्जे का प्रदर्शन लाभ है, यदि आप इतने आश्वस्त हैं, तो आप प्रदर्शन प्रदर्शित करने के लिए jsperf उदाहरण बना सकते हैं। एकमात्र प्रदर्शन जो हमें मिलता है, वह क्लोजर को अलग करने से होता है, जिसके परिणामस्वरूप बेहतर minification होता है जो आकार को कम करता है और स्क्रिप्ट के तेज़ डाउनलोड और पार्सिंग द्वारा प्रदर्शन प्राप्त किया जाता है।
आकाश काव

@AkashKava आपको क्या लगता है कि मैं इतना आश्वस्त हूं ? मैंने अभी कहा "कुछ लाभ हो सकता है" और "मुझे नहीं लगता"। मैं एक परीक्षण बना सकता था, लेकिन मैं नहीं बल्कि इसलिए कि मैंने इस पैटर्न का उपयोग कभी नहीं किया। क्या आप समझा सकते हैं कि "संकलन के समय बंद होने वाले हल" से आपका क्या मतलब है? किस विकल्प के विपरीत? जावास्क्रिप्ट इंजन ने चीजों को पहले कैसे अलग किया?
21

एक ऐसा कोड खोजें जिसमें विंडो अंत में घुली हो लेकिन फ़ंक्शन के मापदंडों में दर्ज नहीं की गई हो, इसका क्या मतलब है? यह सुनिश्चित करता है कि पैरामीटर मूल वैश्विक गुंजाइश ऑब्जेक्ट का पालन करें, भले ही कोई भी विंडो परम नहीं है जो मुझे लगता है?
वेबवुमन
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.