कार्य (कार्य) ({}) () निर्माण कैसे करता है और लोग इसका उपयोग क्यों करते हैं?


79

(function() {})()और इसके jQuery के विशिष्ट चचेरे भाई (function($) {})(jQuery)जावास्क्रिप्ट कोड में हर समय पॉप अप करते हैं।

ये निर्माण कैसे काम करते हैं, और वे किन समस्याओं का समाधान करते हैं?

उदाहरणों की सराहना की



2
यह एक सटीक डुप्लिकेट नहीं है। अन्य प्रश्नों के उत्तर वास्तव में यह नहीं कहते कि एक आपूर्ति क्यों करती हैjQuery तर्क के रूप में करता है।
— जॉर्ज शॉर्ली

1
मुझे हमेशा आश्चर्य होता है कि अतिरिक्त कोष्ठक की आवश्यकता क्यों है। मेरा मानना ​​है कि यह घुंघराले ब्रेस के साथ ब्लॉक और ऑब्जेक्ट शाब्दिक के बीच एक अस्पष्टता के साथ करना है। ध्यान दें कि यदि आप किसी चीज़ को असाइन कर रहे हैं तो वे आवश्यक नहीं हैं, जैसे var x = function () {} () ठीक काम करता है।
— जेपीसिमों

1
यह 'एक वास्तविक प्रश्न के रूप में बंद' क्यों है? प्रश्न स्पष्ट और प्रासंगिक है।
— क्रिस

जवाबों:


73

जावास्क्रिप्ट फ्रेमवर्क की बढ़ती लोकप्रियता के साथ, $कई अलग-अलग अवसरों में संकेत का उपयोग किया गया था। तो, संभावित झड़पों को कम करने के लिए, आप उन निर्माणों का उपयोग कर सकते हैं:

(function ($){
  // Your code using $ here.
})(jQuery);

विशेष रूप से, यह एक अनाम फ़ंक्शन घोषणा है जो पैरामीटर के रूप में तुरंत मुख्य jQuery ऑब्जेक्ट को पारित करने के लिए निष्पादित होती है । उस फ़ंक्शन के अंदर, आप $उस ऑब्जेक्ट को संदर्भित करने के लिए उपयोग कर सकते हैं , अन्य चौखटों के बारे में भी चिंता किए बिना।


4
संक्षिप्त और सार्थक उत्तर। +1!
— पर्व

5
यह तकनीकी रूप से एक फंक्शन एक्सप्रेशन (घोषणा) है। IIFE
— जॉन

क्या आप इसका मतलब समझा सकते हैं: "... अन्य ढांचे के बारे में चिंता किए बिना भी दायरे में है।"
— रेडटॉपिया

@Redtopia जावास्क्रिप्ट स्कोप को फ़ंक्शन स्तर पर परिभाषित किया गया है। एक समारोह के बाहर सब कुछ वैश्विक दायरे में है। एक वेब पेज में कितने जावास्क्रिप्ट शामिल किए गए हैं, इसके बारे में सोचें। एक फंक्शन स्कोप के बाहर प्रत्येक वैरिएबल टक्कर की खतरनाक स्थिति में होता है।
— अल्बर्टो डी कारो

स्पष्ट करने के लिए धन्यवाद ... यह मेरे लिए स्पष्ट नहीं था कि आप गुमनाम फ़ंक्शन के स्थानीय दायरे का उल्लेख कर रहे थे, जिसे वैश्विक दायरे या किसी अन्य फ़ंक्शन के दायरे से नहीं देखा जा सकता है।
— Redtopia

41

यह एक ऐसी तकनीक है जिसका उपयोग चर क्षेत्र को सीमित करने के लिए किया जाता है; यह वैरिएबल को वैश्विक नाम स्थान को प्रदूषित करने से रोकने का एकमात्र तरीका है।

var bar = 1; // bar is now part of the global namespace
alert(bar);

(function () {
   var foo = 1; // foo has function scope
   alert(foo); 
   // code to be executed goes here
})();

7
... और अभी भी आपके कोड के संबंध में उन्हें "वैश्विक" होना चाहिए।
— तवान्फोसन

तो उदाहरण कोड में ओपेरा का संदर्भ अप्रासंगिक / गलत है?
— बॉबी जैक

1
@ लॉबी: उस ब्लॉक के भीतर अतिरिक्त चर / कार्य हो सकते हैं जो केवल ओपेरा के लिए उपयोग किए जाते हैं।
— जियोवा 4

19

1) यह एक अनाम फ़ंक्शन को परिभाषित करता है और इसे सीधे निष्पादित करता है।

2) यह आमतौर पर अवांछित कोड के साथ वैश्विक नाम स्थान को प्रदूषित नहीं करने के लिए किया जाता है।

3) आपको इससे कुछ तरीकों को उजागर करने की आवश्यकता है, अंदर घोषित कुछ भी "निजी" होगा, उदाहरण के लिए:

MyLib = (function(){
    // other private stuff here
    return {
        init: function(){
        }
    };

})();

या, वैकल्पिक रूप से:

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

मुद्दा यह है कि आप इसका उपयोग करने के कई तरीके हैं, लेकिन परिणाम वही रहता है।


1. इस तरह के एक फ़ंक्शन को एक अलग फ़ाइल में परिभाषित किया गया है, यह कैसे निष्पादित करता है? (ऐसा नहीं लगता कि कोई भी इस फ़ंक्शन को कॉल करता है, इसलिए फ़ंक्शन कैसे ट्रिगर होता है?) 2. मैंने यह नहीं देखा कि शीर्ष स्तर पर फ़ंक्शन का "वापसी" कथन है ... मैं dojo.util._doh पढ़ रहा हूं ._browserRunner.js धन्यवाद!
— पॉल

1) जैसा कि मैंने कहा, यह खुद को निष्पादित करता है, आखिरी () इसे निष्पादित करने के लिए कहता है। 2) यह जरूरी नहीं है कि एक वापसी है, यह भी एक विशेष संपत्ति पर मान सेट कर सकते हैं। यह एक उदाहरण मात्र था, जिसका उत्तर मैंने एक और संभावना के साथ दिया।
— इवान ट्रिंबोली

9

यह सिर्फ एक अनाम फ़ंक्शन है जिसे तुरंत कहा जाता है। आप पहले फ़ंक्शन बना सकते हैं और फिर उसे कॉल कर सकते हैं, और आपको समान प्रभाव मिलेगा:

(function(){ ... })();

के रूप में काम करता है:

temp = function(){ ... };
temp();

आप एक नामित फ़ंक्शन के साथ भी ऐसा कर सकते हैं:

function temp() { ... }
temp();

कोड जिसे आप jQuery- विशिष्ट कहते हैं, केवल इस अर्थ में है कि आप इसमें jQuery ऑब्जेक्ट का उपयोग करते हैं। यह एक पैरामीटर के साथ सिर्फ एक अनाम फ़ंक्शन है, जिसे तुरंत कहा जाता है।

आप दो चरणों में एक ही काम कर सकते हैं, और आप इसे किसी भी पैरामीटर के साथ कर सकते हैं जो आपको पसंद है:

temp = function(answer){ ... };
temp(42);

समस्या यह है कि यह हल करती है कि यह फ़ंक्शन में कोड के लिए एक क्लोज़्यूज़ बनाता है। आप वैश्विक नाम स्थान को प्रदूषित किए बिना इसमें चर घोषित कर सकते हैं, इस प्रकार एक स्क्रिप्ट को दूसरे के साथ प्रयोग करते समय टकराव के जोखिम को कम कर सकते हैं।

JQuery के लिए विशिष्ट मामले में आप इसे संगतता मोड में उपयोग करते हैं जहां यह jQuery के लिए उपनाम के रूप में $ $ की घोषणा नहीं करता है। JQuery ऑब्जेक्ट को क्लोजर में भेजने और पैरामीटर $ का नामकरण करके आप अभी भी संगतता मोड के बिना समान सिंटैक्स का उपयोग कर सकते हैं।


जैसा कि मैंने @ स्पूल्सन के उत्तर पर टिप्पणी की, एक अनाम फ़ंक्शन एक क्लोजर के समान नहीं है।
— टिम डाउन

7

यह यहाँ बताता है कि आपका पहला निर्माण चरों के लिए गुंजाइश प्रदान करता है।

जावास्क्रिप्ट में फंक्शन लेवल पर वेरिएबल्स को स्कैन किया जाता है। यह आपके लिए C # या जावा जैसी भाषा में उपयोग किया जा सकता है, जहां चर खंड में ब्लॉक किए गए हैं। इसका मतलब क्या है यदि आप एक लूप के अंदर एक चर घोषित करते हैं या यदि एक बयान है, तो यह पूरे फ़ंक्शन के लिए उपलब्ध होगा।

यदि आप कभी भी अपने आप को एक फ़ंक्शन के अंदर एक चर को स्पष्ट रूप से गुंजाइश करने की आवश्यकता पाते हैं तो आप ऐसा करने के लिए एक अनाम फ़ंक्शन का उपयोग कर सकते हैं। आप वास्तव में एक अनाम फ़ंक्शन बना सकते हैं और फिर उसे सीधे निष्पादित कर सकते हैं और अंदर के सभी चर अनाम फ़ंक्शन पर स्कोप किए जाएंगे:

(function() {
  var myProperty = "hello world";
  alert(myProperty);
})();
alert(typeof(myProperty)); // undefined

6

ऐसा करने का एक अन्य कारण यह है कि $आप किस फ्रेमवर्क के ऑपरेटर का उपयोग कर रहे हैं, इस पर कोई भ्रम दूर करना है। उदाहरण के लिए, jQuery को बाध्य करने के लिए, आप यह कर सकते हैं:

;(function($){
   ... your jQuery code here...
})(jQuery);

$ऑपरेटर के रूप में एक पैरामीटर के रूप में गुजरने और इसे jQuery पर लागू करने से, $फ़ंक्शन के भीतर का ऑपरेटर jQuery के लिए लॉक हो जाता है, भले ही आपके पास अन्य फ्रेमवर्क लोड हो।


यह मूल प्रश्न पर अधिक विशिष्ट भिन्नता है, लेकिन यह अभी भी अच्छी जानकारी है! :)
— बॉबी जैक

एक जवाब बिल्कुल नहीं है, लेकिन मैंने इसे आपके शानदार विचार के लिए लिया है!
— स्पाइडी

5

इस निर्माण के लिए एक और उपयोग स्थानीय चर के मूल्यों को "कैप्चर" करना है जो एक क्लोजर में उपयोग किया जाएगा। उदाहरण के लिए:

for (var i = 0; i < 3; i++) {
    $("#button"+i).click(function() {
        alert(i);
    });
}

उपरोक्त कोड तीनों बटन "3" को पॉप अप कर देगा। दूसरी ओर:

for (var i = 0; i < 3; i++) {
    (function(i) {
        $("#button"+i).click(function() {
            alert(i);
        });
    })(i);
}

यह तीन बटन "0", "1", और "2" को अपेक्षित रूप से पॉप अप करेगा।

इसका कारण यह है कि एक बंद अपने संलग्नक स्टैक फ्रेम का संदर्भ रखता है , जो इसके चर के मौजूदा मूल्यों को रखता है। यदि क्लोजर निष्पादित होने से पहले वे चर बदल जाते हैं, तो क्लोजर केवल नवीनतम मानों को देखेगा, न कि उन मानों को, जैसा कि उस समय था जब क्लोजर बनाया गया था। ऊपर के दूसरे उदाहरण के रूप में किसी अन्य फ़ंक्शन के अंदर क्लोजर निर्माण को लपेटकर i, अनाम फ़ंक्शन के स्टैक फ्रेम में चर के वर्तमान मूल्य को बचाया जाता है।


एक छोटी सी नाइटपिक, लेकिन यह स्टैक फ्रेम नहीं है जो कि बंद है, यह आसपास का शाब्दिक स्कोप है। क्लोजर के अच्छे कार्यान्वयन केवल उन प्रतीकों को कैप्चर करेंगे जो वास्तव में क्लोजर के अंदर उल्लिखित हैं, कुछ कार्यान्वयन केवल सब कुछ कैप्चर करते हैं (रूबी ऐसा करता है, इसलिए सावधान रहें कि आपके पास क्लोजर क्या है)। ओओपी में एक वस्तु के बारे में सोचने का एक तरीका एक बंद करने के रूप में है जहां कैप्चर किए गए प्रतीकों को स्पष्ट रूप से परिभाषित किया गया है (ऑब्जेक्ट के सदस्य गुण)।
— KayEss

यह सच है, लेकिन यह वास्तव में सिर्फ एक कार्यान्वयन मुद्दा है और वैचारिक रूप से कोई भी विचार कर सकता है कि स्टैक फ्रेम को क्लोजर द्वारा संदर्भित किया गया है। लिस्प परिवार की भाषाओं में ओओपी-शैली "ऑब्जेक्ट" सभी क्लोजर के साथ किया जाता है, यह एक शक्तिशाली तकनीक है।
— ग्रेग हेवगिल

हां, हालांकि यदि आप स्टैक फ्रेम के संदर्भ में सोचना चाहते हैं, तो बंद करना स्टैक फ्रेम की एक श्रृंखला है, जो वैश्विक दायरे के साथ लेक्सिकल दायरे में प्रत्येक एन्कोडिंग फ़ंक्शन के लिए एक फ्रेम है। लेक्सिकल स्कोप के बारे में सोचना आसान है (विशेषकर किसी ऐसे व्यक्ति को समझाते हुए, जो बंद करने के लिए नया है) क्योंकि आप एक व्यर्थ (और भ्रामक) चर्चा में नहीं पड़ते हैं जिसके बारे में स्टैक फ्रेम तब होता है जब आपके पास कई स्तर के नेस्टेड फ़ंक्शन होते हैं। लेक्सिकल स्कोप बस वही है जो आप सोर्स कोड में देखते हैं।
— KayEss

4

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

var i = 0;
alert("The magic number is " + i);

(function() {
   var i = 99;
   alert("The magic number inside the closure is " + i);
})();

alert("The magic number is still " + i);

यह तीन पॉपअप उत्पन्न करेगा, यह दर्शाता है कि iक्लोजर समान नाम के पहले से मौजूद चर को नहीं बदलता है:

  • जादू की संख्या 0 है
  • क्लोजर के अंदर मैजिक नंबर 99 है
  • जादू की संख्या अभी भी 0 है

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

बस "(फ़ंक्शन () {..." को "var func = function () {...}; func ();" में
— बदलें

मैं यह श्रम नहीं करना चाहता, लेकिन ... अभी भी कोई बंद नहीं है: बाहरी फ़ंक्शन के बाहर कोई आंतरिक कार्य नहीं किया जा रहा है। अपने उदाहरण में एक क्लोजर बनाने का एक आसान तरीका एक फ़ंक्शन को वापस करना होगा जो मैंने चेतावनी दी थी: var f = (function () {var i = 99; return function () {अलर्ट (i);};}) (); च ();
— टिम डाउन

बिंदु ने नोट किया। यह कार्यान्वयन की बारीकियों के लिए नीचे आता है।
— spoulson

2

वे अक्सर jQuery प्लगइन्स में उपयोग किया जाता है। जैसा कि jQuery प्लगइन्स ऑथरिंग गाइड में बताया गया है कि अंदर घोषित सभी वैरिएबल { }निजी हैं और बाहर से दिखाई नहीं देते हैं जो बेहतर एनकैप्सुलेशन की अनुमति देता है।


3
{}अपने आप में नहीं और जावास्क्रिप्ट में एक नया दायरा बनाएँ। कार्यक्षेत्र घोषणा द्वारा बनाया गया है।
— एनाबेले

2

जैसा कि दूसरों ने कहा है, वे दोनों उन अनाम कार्यों को परिभाषित करते हैं जो तुरंत लागू होते हैं। मैं आम तौर पर इस संरचना में अपने जावास्क्रिप्ट वर्ग घोषणाओं को लपेटता हूं ताकि कक्षा के लिए एक स्थिर निजी गुंजाइश बनाई जा सके। मैं तब लगातार डेटा, स्थिर विधियों, घटना संचालकों, या उस दायरे में और कुछ भी रख सकता हूं और यह केवल कक्षा के उदाहरणों के लिए दिखाई देगा:

// Declare a namespace object.
window.MyLibrary = {};

// Wrap class declaration to create a private static scope.
(function() {
  var incrementingID = 0;

  function somePrivateStaticMethod() {
    // ...
  }

  // Declare the MyObject class under the MyLibrary namespace.
  MyLibrary.MyObject = function() {
    this.id = incrementingID++;
  };

  // ...MyObject's prototype declaration goes here, etc...
  MyLibrary.MyObject.prototype = {
    memberMethod: function() {
      // Do some stuff
      // Maybe call a static private method!
      somePrivateStaticMethod();
    }
  };
})();

इस उदाहरण में, MyObjectवर्ग MyLibraryनाम स्थान को सौंपा गया है, इसलिए यह सुलभ है। incrementingIDऔर somePrivateStaticMethod()अनाम फ़ंक्शन दायरे के बाहर सीधे पहुंच योग्य नहीं हैं।


2

यह मूल रूप से आपके जावास्क्रिप्ट कोड को नाम स्थान देने के लिए है।

उदाहरण के लिए, आप किसी भी चर या कार्य को वहां और बाहर से रख सकते हैं, वे उस दायरे में मौजूद नहीं हैं। इसलिए जब आप सब कुछ वहाँ करते हैं, तो आपको झड़पों के बारे में चिंता करने की ज़रूरत नहीं है।

()स्वयं आह्वान करने के लिए अंत का मतलब है पर। आप वहां एक तर्क भी जोड़ सकते हैं जो आपके अनाम फ़ंक्शन का तर्क बन जाएगा। मैं jQuery के साथ अक्सर ऐसा करता हूं, और आप देख सकते हैं कि क्यों ...

(function($) {

    // Now I can use $, but it won't affect any other library like Prototype
})(jQuery);

इवान ट्रिंबोली ने अपने जवाब में बाकी को शामिल किया है ।


1

यह एक सेल्फ-इन्वोकिंग फंक्शन है। लिखने के लिए आशुलिपि की तरह

function DoSomeStuff($)
{
}

DoSomeStuff(jQuery);

1

उपरोक्त कोड क्या कर रहा है लाइन 1 पर एक अनाम फ़ंक्शन बना रहा है, और फिर इसे 0 तर्क के साथ लाइन 3 पर कॉल कर रहा है। यह उस पुस्तकालय के भीतर परिभाषित सभी कार्यों और चर को प्रभावी ढंग से संलग्न करता है, क्योंकि सभी फ़ंक्शन केवल उस अनाम फ़ंक्शन के अंदर ही सुलभ होंगे।

यह अच्छा अभ्यास है, और इसके पीछे तर्क यह है कि वैश्विक नाम स्थान को चर और कार्यों के साथ प्रदूषित करने से बचा जाए, जो कि पूरे साइट पर जावास्क्रिप्ट के अन्य टुकड़ों द्वारा बंद किया जा सकता है।

यह स्पष्ट करने के लिए कि फ़ंक्शन को कैसे कहा जाता है, सरल उदाहरण पर विचार करें:

यदि आपके पास जावास्क्रिप्ट की यह एकल पंक्ति शामिल है, तो यह स्पष्ट रूप से कॉल किए बिना स्वचालित रूप से आह्वान करेगा:

alert('hello');

तो, उस विचार को लें, और इसे इस उदाहरण पर लागू करें:

(function() {
    alert('hello')
    //anything I define in here is scoped to this function only
}) (); //here, the anonymous function is invoked

अंतिम परिणाम समान है, क्योंकि अनाम फ़ंक्शन पिछले उदाहरण की तरह ही लागू किया गया है।


कृपया इवान के लिए टिप्पणियों का मेरा पहला प्रश्न देखें ... धन्यवाद!
— पॉल

//here, the anonymous function is invoked, सरल, लेकिन मैंने इसे पहले नहीं देखा :)
— स्टीफन

1

क्योंकि अच्छे कोड के उत्तर पहले से ही ले लिए गए हैं :) मैं कुछ जॉन रेसिग वीडियो 1 , वीडियो 2 (जावास्क्रिप्ट में jQuery और मास्टर का आविष्कारक) देखने के सुझाव में फेंकूंगा ।

कुछ वास्तव में अच्छी अंतर्दृष्टि और वीडियो में दिए गए उत्तर।

यही वह क्षण था जब मैं आपके प्रश्न को देख रहा था।


0
function(){ // some code here }

जावास्क्रिप्ट में एक अनाम फ़ंक्शन को परिभाषित करने का तरीका है। वे आपको एक फ़ंक्शन को किसी अन्य फ़ंक्शन के संदर्भ में निष्पादित करने की क्षमता दे सकते हैं (जहां आपके पास अन्यथा वह क्षमता नहीं हो सकती है)।

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