2013-03-30 11 views
10

यह पहले से ही कई बार पूछे जा सकते हैं, और मैंने एसओ के आसपास खोज की है लेकिन अब तक मेरे द्वारा पढ़े गए सभी उत्तरों ठीक वही नहीं हैं जो मैं ढूंढ रहा हूं।ऑब्जेक्ट लिटलल या मॉड्यूलर जावास्क्रिप्ट डिज़ाइन पैटर्न

मैं एक वेबसाइट पर काम कर रहा हूं जिसमें मध्यम डोम तत्व दिख रहे हैं/छुपा रहे हैं, कुछ AJAX कॉल, और शायद कुछ और। इसलिए मैं दो मुख्य स्क्रिप्ट फ़ाइलें (एचटीएमएल 5 बॉयलरप्लेट मानक)

plugins.js // third party plugins here 
site.js // all my site specific code here 

पहले मैं वस्तु शाब्दिक डिजाइन पैटर्न का उपयोग कर रहा होने वाले हैं, इसलिए मेरी site.js कुछ इस तरह है: तो

var site = { 
    version: '0.1', 
    init: function() { 
    site.registerEvents(); 
    }, 
    registerEvents: function() { 
    $('.back-to-top').on('click', site.scrollToTop); 
    }, 
    scrollToTop: function() { 
    $('body').animate({scrollTop: 0}, 400); 
    } 
}; 

$(function() { 
    site.init(); 
}); 

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

site.auth = { 
    init: function() { 
    site.auth.doms.loginButton.on('click', site.auth.events.onLoginButtonClicked); 
    }, 
    doms: { 
    loginButton: $('.login'), 
    registerButton: $('.register') 
    }, 
    events: { 
    onLoginButtonClicked: function() { 
    } 
    }, 
    fbLogin: function() { 
    } 
}; 

site.dashboard = { 
}; 

site.quiz = { 
}; 

// more modules 

आप देख सकते हैं, यह बहुत है पठनीय। हालांकि एक स्पष्ट नकारात्मक पक्ष है, जिसे मुझे site.auth.doms.loginButton और site.auth.events.onLoginButtonClicked जैसे कोड लिखना है। अचानक इसे पढ़ना मुश्किल हो जाता है, और यह केवल कार्यक्षमता प्राप्त होने के लिए अधिक जटिल हो जाएगा। तब मैं मॉड्यूलर पैटर्न की कोशिश की:

var site = (function() { 
    function init() { 
    $('.back-to-top').on('click', scrollToTop); 
    site.auth.init(); 
    } 

    function scrollToTop() { 
    $('body').animate({scrollTop: 0}, 400); 
    } 

    return { 
    init: init 
    } 
})(); 

site.auth = (function() { 
    var doms = { 
    loginButton: $('.login'), 
    registerButton: $('.register') 
    }; 

    function init() { 
    doms.loginButton.on('click', onLoginButtonClicked); 
    } 

    function onLoginButtonClicked() { 

    } 

    return { 
    init: init 
    } 
})(); 

// more modules 

आप देखते हैं, उन लंबे नामों चले गए हैं कर सकते हैं, लेकिन फिर मैं मैं site.init() फ़ंक्शन में अन्य सभी मॉड्यूल init करने के लिए उन सब को निर्माण करने के लिए है लगता है? तो मुझे उन कार्यों को वापस करना याद रखना होगा जिन्हें अन्य मॉड्यूल द्वारा सुलभ करने की आवश्यकता है। उनमें से दोनों ठीक हैं, मुझे लगता है कि थोड़ा परेशानी है, लेकिन कुल मिलाकर, क्या मैं मॉड्यूलर पैटर्न के साथ काम कर रहे बेहतर वर्कफ़्लो पर हूं?

+0

'this.doms.loginButton.on ('क्लिक करें', this.events.onLoginButtonClicked) के बारे में क्या;'? – Bergi

+0

यह काम कर सकता है, विश्वास नहीं कर सकता मैंने कोशिश नहीं की। लेकिन मॉड्यूलर पैटर्न की तुलना में लिखना अभी भी काफी लंबा है। – Henson

उत्तर

15

सही उत्तर, यहां, यह है: "यह निर्भर करता है"।

यदि आप पूरी तरह से सभी डेटा और सभी विधियों के साथ ठीक हैं, तो आपकी साइट के प्रत्येक अनुभाग में 100% सार्वजनिक होने के बाद, केवल एक शाब्दिक (या एकाधिक अक्षर) का उपयोग करके, नेस्टेड ऑब्जेक्ट्स के साथ वांछित, पूरी तरह से ठीक है, यह मानते हुए कि आप इसे कोड की एक विशाल गेंद में बदलने से रोक सकते हैं।

यदि आप किसी भी तरह का निजी राज्य चाहते हैं, जिसमें किसी भी तरह की दृढ़ता है (यानी: जब भी आप कोई फ़ंक्शन चलाते हैं) रीसेट नहीं करता है, तो खुलासा-मॉड्यूल बहुत अच्छा है।

यह कहा गया:
आपके लिए .init विधि के लिए खुलासा-मॉड्यूल की आवश्यकता नहीं है।
यदि आपका मॉड्यूल स्वयं निहित हो सकता है, तो केवल सार्वजनिक करने के लिए आप क्या करना चाहते हैं निर्यात पर ध्यान केंद्रित करें।

इस अंत में, जब मैं एक कोड लिख रहा हूं, जो बाद में, मैं खुद को public_interface ऑब्जेक्ट बना रहा हूं और इसे लौटा रहा हूं (आपके द्वारा लौटाए गए अज्ञात ऑब्जेक्ट का नामित संस्करण)।

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

जिस तरह से आप वर्तमान में इसका उपयोग कर रहे हैं:

var module = (function() { /* ... */ return {}; }()); 

module.submodule = (function() { /*...*/ return {}; }()); 

कोई बेहतर या शाब्दिक से भी बदतर है, क्योंकि आप बस के रूप में आसानी से कर सकते हैं: जब तक आप कुछ है जो नहीं करता है हिट

var module = { 
    a : "", 
    method : function() {}, 
    meta : { } 
}; 

module.submodule = { 
    a : "", 
    method : function() {}, 
    meta : { } 
}; 

आपके लिए काम नहीं करता, आपकी जरूरतों को पूरा करने के साथ काम करें। config-वस्तुओं, जिन वस्तुओं पर अन्य कनेक्शन से में आते हैं, आदि

किसी भी गंदगी-सरल वस्तु जो शायद एक या दो की आवश्यकता है ...:

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

// ex: 
var rectangle = { 
    width : 12, 
    height : 24, 
    area : 0, 
    perimeter : 0, 
    init_area : function() { this.area = this.width * this.height; return this; }, // buh... 
    init_perimeter : function() { this.perimeter = (this.width * 2) + (this.height * 2); return this; } // double-buh... 
}.init_area().init_perimeter(); 

अगर मैं इनमें से कई की जरूरत है, शायद मैं एक निर्माता बनाने चाहते हैं।
लेकिन अगर मैं ही कभी कुछ इस तरह से एक अद्वितीय की जरूरत है, यह मुझे कुछ सिर दर्द को बचाने नहीं होगा सिर्फ इस तरह कुछ करने के लिए:

var rectangle = (function (width, height) { 
    var public_interface = { 
     width : width, 
     height : height, 
     area : width * height, 
     perimeter : (2 * width) + (2 * height) 
    }; 
    return public_interface; 
}(12, 24)); 

अगर वहाँ अधिक उन्नत गणना के लिए आवश्यक थे, मैं रख सकता है किसी भी अतिरिक्त वर्र्स निजी, और अंदर से उन पर काम करते हैं।
यदि मुझे किसी ऑब्जेक्ट के अंदर संवेदनशील डेटा होना चाहिए, और उस डेटा पर काम करने के लिए फ़ंक्शंस की आवश्यकता है, तो मेरे पास सार्वजनिक-फ़ंक्शन हो सकते हैं जो उन निजी कार्यों को कॉल करते हैं, और पहुंच प्रदान करने के बजाय परिणाम लौटाते हैं।

इसके अलावा, अगर मैं अपने कोड refactor, और कुछ बिंदु पर rectangle नाम बदलने के लिए निर्णय लेते हैं, तो किसी भी कार्य करता नेस्ट 3 या उससे अधिक गहरा है, जो rectangle की बात कर रहे संशोधित करने की है, साथ ही होगा।
फिर, अगर आप अपने तरीकों की संरचना रहे हैं ताकि वे सीधे किसी भी वस्तु जो this से आगे है के लिए पूछने की जरूरत नहीं है, तो आप इस समस्या है नहीं होगा ...

... लेकिन यदि आप एक अंतरफलक है कि तरह दिखता है:

MyApp.myServices.webService.send(); 

और यह पता लगाने के लिए उम्मीद कर रहा है:

MyApp.appData.user.tokens.latest; // where personally, I might leave tokens in a closure 

आप अपने AppData मॉड्यूल की संरचना में परिवर्तन हैं, तो आप में त्रुटियों के सभी प्रकार करने जा रहे हैं आपका वेब सेवा मॉड्यूल , जब तक कि आप पुराने प्रारूप के हर संदर्भ को न ढूंढें, और उन सभी का नाम बदलें।

+0

तो किसी भी मामले में, इसलिए गोपनीयता और व्यक्तिगत वरीयता के अलावा ऑब्जेक्ट लिटल बनाम मॉड्यूलर का उपयोग करने के बीच कोई वास्तविक पेशेवर/विपक्ष नहीं है? – Henson

+1

@ ऑब्सन और आंतरिक संदर्भ, ऑब्जेक्ट लिटलल के भीतर, उन गुणों के लिए जो अन्य गुणों पर भरोसा करते हैं, जिन्हें तथ्य के बाद गणना की जानी चाहिए, या ऑब्जेक्ट के तरीकों के भीतर बंद करना, जिसके लिए गुणों की आवश्यकता होती है जब आप पहले से मौजूद हों समारोह बनाने की कोशिश कर रहा है ... यह सब जटिलता के लिए नीचे आता है। यदि आप अपने सभी ऑब्जेक्ट-निर्माण का प्रबंधन कर सकते हैं ताकि आपकी सभी बड़ी वस्तुएं केवल बहुत अधिक कच्चे डेटा हों, फिर ऑब्जेक्ट्स अक्षर ठीक हैं। यदि आपको बंद करने की आवश्यकता है, या ऑब्जेक्ट के पूर्व-मौजूदा सदस्यों के आधार पर पूर्व-गणना करने की आवश्यकता है, तो शब्दशः '{} .init()' – Norguard

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