2011-03-06 18 views
28

source code for CoffeeScript on Github की समीक्षा करते हुए मैंने देखा है कि सबसे, इस प्रकार यदि सभी नहीं, मॉड्यूल की परिभाषित कर रहे हैं: जैसे कि यह एक गुमनाम समारोह में पूरे मॉड्यूल लपेटता है औरपैटर्न मॉड्यूल

(function() { 
    ... 
}).call(this); 

यह पैटर्न लग रहा है खुद को बुलाता है

इस दृष्टिकोण के पेशेवर (और विपक्ष) क्या हैं? क्या एक ही लक्ष्य को पूरा करने के अन्य तरीके हैं?

+5

ध्यान दें कि आप उत्पन्न जावास्क्रिप्ट, नहीं लिखा coffeescript देख रहे हैं। – Dykam

उत्तर

77

हरमन का जवाब काफी अच्छा है, लेकिन मुझे कॉफीस्क्रिप्ट कंपाइलर और क्यों किया जाता है, इस पर थोड़ा सा विस्तार करने दें।

(function() { 
    ... 
}).call(this); 

कि क्यों है:

जब आप coffee -c foo.coffee के साथ कुछ संकलन, आप हमेशा एक foo.js कि इस तरह दिखता है मिलेगा? ठीक है, आप

x = 'stringy string' 

foo.coffee में की तरह एक काम कर दिया लगता है। जब यह देखता है, संकलक पूछता है: क्या x पहले से ही इस दायरे में या बाहरी दायरे में मौजूद है? यदि नहीं, तो यह जावास्क्रिप्ट आउटपुट में उस दायरे के शीर्ष पर var x घोषणा करता है।

अब आप bar.coffee में लिखने

x = 42 

, दोनों संकलन, और तैनाती के लिए bar.js साथ foo.js श्रेणीबद्ध लगता है।आप मिल जाएगा

(function() { 
    var x; 
    x = 'stringy string'; 
    ... 
}).call(this); 
(function() { 
    var x; 
    x = 42; 
    ... 
}).call(this); 

तो foo.coffee में x और bar.coffee में x एक दूसरे से पूरी तरह से अलग कर रहे हैं। यह CoffeeScript का एक महत्वपूर्ण हिस्सा है: चर एक .coffee फ़ाइल से दूसरे में रिसाव कभी नहीं जब तक स्पष्ट (एक Node.js में वैश्विक साझा, या exports करने के लिए संलग्न किया जा रहा द्वारा) का निर्यात किया।

आप -b ("bare") ध्वज coffee पर उपयोग करके इसे ओवरराइड कर सकते हैं, लेकिन इसका उपयोग केवल विशेष मामलों में किया जाना चाहिए। यदि आपने उपर्युक्त उदाहरण के साथ इसका उपयोग किया है, तो आपको प्राप्त होने वाला आउटपुट

var x; 
x = 'stringy string'; 
... 
var x; 
x = 42; 
... 

इससे गंभीर परिणाम हो सकते हैं। इस अपने आप को परीक्षण करने के लिए, foo.coffee में setTimeout (-> alert x), 1 जोड़ने का प्रयास करें। और ध्यान दें कि आप दो जे एस श्रेणीबद्ध की जरूरत नहीं है कि अपने आप को-यदि फ़ाइलें आप उन्हें एक पृष्ठ पर शामिल करने के लिए दो अलग-अलग <script> टैग का उपयोग, वे अभी भी प्रभावी रूप से एक फ़ाइल के रूप में चलाते हैं।

विभिन्न मॉड्यूल का स्कोप अलग करके, CoffeeScript संकलक चिंता अपनी परियोजना में विभिन्न फ़ाइलें एक ही स्थानीय चर नाम का उपयोग कर सकते हैं कि क्या की सिर दर्द से बचाता है। यह (बस के बारे में कोई jQuery प्लगइन देखते हैं, उदाहरण के लिए, jQuery source, या) जावास्क्रिप्ट दुनिया में आम बात -CoffeeScript सिर्फ तुम्हारे लिए यह का ध्यान रखता है।

+1

उत्कृष्ट रणनीति! – lo5

+4

आपका उत्तर अच्छी तरह लिखा गया था और वास्तव में मुझे कॉफीस्क्रिप्ट (और जावास्क्रिप्ट) को बेहतर समझने में मदद करता है ... धन्यवाद! –

+1

कौन सा बिल्ली वैश्विक वैरिएबल के साथ खेलता है? मैं कक्षा या बंद होने के बिना कुछ भी करने के बारे में नहीं सोचूंगा। स्पष्ट रूप से निर्यात करना अप्रिय है। – Duke

19

इस दृष्टिकोण के बारे में अच्छी बात यह है कि यह निजी चर बनाता है, इसलिए चर नाम के साथ कोई द्वंद्व नहीं होगा:

(function() { 
    var privateVar = 'test'; 
    alert(privateVar); // test 
})(); 

alert(typeof privateVar); // undefined 

.call(this) के अलावा this कीवर्ड एक ही मूल्य के रूप में उल्लेख करता है यह समारोह के बाहर संदर्भित किया जाता है। यदि यह जोड़ा नहीं गया है, तो this कीवर्ड स्वचालित रूप से वैश्विक वस्तु का संदर्भ देगा।

एक छोटा सा उदाहरण अंतर दिखाने के लिए इस प्रकार है:

function coffee(){ 
    this.val = 'test'; 
    this.module = (function(){ 
    return this.val; 
    }).call(this); 
} 

var instance = new coffee(); 
alert(instance.module); // test 

function coffee(){ 
    this.val = 'test'; 
    this.module = (function(){ 
    return this.val; 
    })(); 
} 

var instance = new coffee(); 
alert(typeof instance.module); // undefined 
+0

अच्छा जवाब। आपकी सहायताके लिए धन्यवाद! –

1

यह इस के समान वाक्य रचना है:

(function() { 

}()); 

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

var MY_MODULE = (function() { 
    //local variables 
    var variable1, 
     variable2, 
     _self = {}, 
     etc 

    // public API 
    _self = { 
     someMethod: function() { 

     } 
    } 

    return _self; 
}()); 

यकीन नहीं क्या विपक्ष वास्तव में हो सकता है, किसी और किसी भी जानता है अगर मैं उनके बारे में जानने के लिए खुशी होगी:

इस विशिष्ट पैटर्न मैं का उपयोग जब एक मॉड्यूल लेखन है।

+0

मैं कहूंगा कि विपक्ष 1 है) आपको मॉड्यूल में राज्य को साझा करने के लिए थोड़ा कठिन काम करना होगा (कम से कम कॉफीस्क्रिप्ट में- जावास्क्रिप्ट में, आप 'var' को छोड़ सकते हैं, लेकिन यह आमतौर पर निराश होता है, उदाहरण के लिए जेएसलिंट द्वारा), और 2) अतिरिक्त फ़ंक्शन कॉल और बाइट्स से ओवरहेड का एक छोटा सा हिस्सा है। लेकिन 99% समय, अतिरिक्त सुरक्षा इसके लायक है। –

+0

नहीं, यह एक संबंधित उत्तर नहीं है। वह पूछ रहा है (फ़ंक्शन() {})। कॉल (यह) विशेष रूप से, नहीं (फ़ंक्शन() {})() जैसा कि आपने उदाहरण दिया है। हार्मन का जवाब बिंदु पर है। –

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