2012-02-14 10 views
26

मैं अपने नोडजेएस अनुप्रयोग को ढूढ़ने के लिए मॉड्यूल बनाना चाहता हूं, लेकिन मैं थोड़ा खो गया हूं, और मुझे कुछ भी नहीं मिला है (खोज के घंटों के साथ) जो विषय पर पूरी तरह से निश्चित है ।एक नोडजेएस मॉड्यूल का निर्माण - चर और विधियां

var newUser = new User(); 

आदर्श रूप में, मैं के शीर्ष पर मेरी मॉड्यूल की आवश्यकता होगी:

मैं एक "उपयोगकर्ता" मॉड्यूल बनाना चाहते हैं, जिसमें से मैं की तरह कुछ का उपयोग कर मेरी कोड में नए उपयोगकर्ताओं को बना सकते हैं कहो मेरा कोड कुछ ऐसा उपयोग कर रहा है:

var User = require('../lib/user'); 

यह बहुत अच्छा काम करता है। सवाल यह है कि, मैं उपयोगकर्ता मॉड्यूल को कैसे ढूढ़ूं? क्या निम्नतम तरीका सबसे अच्छा तरीका है?

module.exports = function User() { 
    var authorized = false; 
    var username = undefined; 
    var password = undefined; 
    var statistics = undefined; 

    this.authorized = function() { 
     return authorized; 
    } 
    this.username = function() { 
     return username; 
    } 
    this.statistics = function() { 
     return statistics; 
    } 
} 

मैं अपने विभिन्न मॉड्यूल चर के लिए getters और setters लिख रहा हूँ, मुझे बातें मैंने गलती से अन्य कोड से उपयोग करने के लिए नहीं करना चाहते हैं छिपाने के लिए अनुमति देता है। हालांकि, मैंने इसे पहले इस तरह से किया है:

function User() { 
    this.authStatus = false; 
    this.email; 
    this.displayName; 
    this.inSession; 
} 

User.prototype.isAuthenticated = function() { 
    return(this.authStatus && this.email && this.displayName) 
} 

User.prototype.isInSession = function() { 
    return(this.inSession && this.isAuthenticated()); 
} 

exports.User = User; 

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

User.prototype.login = function() { 
    db.doDbStuff('get user data query', function(_error, _result) { 
     this.username = _result[0].name; //this code will not work 
    }); 
} 

कोड काम नहीं करता है, मेरी समझ है, क्योंकि "इस" कीवर्ड बंद, नहीं उपयोगकर्ता के दायरे के भीतर है। भले ही कोड उपयोगकर्ता फ़ंक्शन के भीतर रखा जाना था:

function User() { 
    this.login = function() { //you know 

यह काम नहीं करेगा।

मुझे लगता है कि मेरा सवाल है, इस समस्या का सबसे अच्छा समाधान क्या है? क्या यह पहला कोड ब्लॉक में प्रस्तुत किया गया तरीका है? ऐसा लगता है कि यह बोझिल और गन्दा और परिवर्तनीय टकराव के लिए प्रवण है। मुझे डर लग रहा है।

अग्रिम धन्यवाद!

+2

यदि इनमें से कोई भी समझ में नहीं आया, तो मैं पहले से माफ़ी मांगता हूं, मैंने अपने ज्ञान दांतों के लिए कुछ दर्द दवा ली और मुझे थोड़ी हल्की और फंकी लगती है। –

+1

आम तौर पर node.js के साथ करने के बजाए जावास्क्रिप्ट आर्किटेक्चर के दायरे में अधिक खून बहता है। http://speakerdeck.com/u/addyosmani/p/scaling-your-javascript- एप्प्लिकेशंस और http://www.slideshare.net/SlexAxton/superclassy-inheritance-in-javascript काफी अच्छे हैं। – balupton

+0

यह ध्यान देने योग्य है कि आपके दोनों उदाहरणों में चर निजी नहीं हैं। आपको यह देखना चाहिए: http://javascript.crockford.com/private.html –

उत्तर

24

मैं आमतौर पर प्रोटोटाइप के कार्यों को जोड़ने, दूसरे दृष्टिकोण के साथ जाता हूं।

आपके पास वेरिएबल्स के साथ होने वाली समस्या "बंद होने में उपलब्ध नहीं है" प्रोटोटाइप के साथ कुछ भी नहीं है। आपके पास वही समस्या होगी जिस तरह से आप इसे बनाते हैं।

यह के साथ क्या करना है जावास्क्रिप्ट का बार-बार भ्रमित गतिशील this:

User.prototype.login = function() { 
    var self = this // bind this to self so you have a reference to what `this` was 

    db.doDbStuff('get user data query', function(_error, _result) { 
     self.username = _result[0].name; // self refers to the original `this`, so this works. 
    }); 
} 

तुम भी समारोह का उपयोग करने का विकल्प होता है: http://robotlolita.me/2011/10/09/understanding-javascript-oop.html#sec-2-1

मूल रूप से, आप की तरह कुछ करने की ज़रूरत है।बाँध: https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Function/bind

बाध्य समारोह के भीतर, this का मूल्य आप जो भी मान .bind(value) करने के लिए प्रदान किया जाएगा:

User.prototype.login = function() { 
    db.doDbStuff('get user data query', (function(_error, _result) { 
     this.username = _result[0].name; // bind fixes the original `this`, so this also works. 
    }).bind(this)); 
} 

चाहे आप का उपयोग function.bind या self = this एक व्यक्तिगत स्वाद सवाल का कुछ हद तक है, लेकिन हम क्या कर रहे थे दूसरे दिन freenode # nodejs में कुछ बेंचमार्क और bind() की खोज var self = this से 20 गुना धीमी है।

मॉड्यूल को कैसे व्यवस्थित करने के बारे में आपके मूल प्रश्न के रूप में, जिथब से सीखने के लिए कई उदाहरण हैं। बस अपना पसंदीदा मॉड्यूल पाएं और निरीक्षण करें कि वे इसे कैसे बनाते हैं। मैंने देखा है कि कई लोग सीधे रचनाकारों को उजागर करने पर कारखानों को पसंद करते हैं (उदाहरण के लिए require('module').create())। तुम्हारा कॉल।

+1

ओह। यह इतना शानदार और सरल है! Jeeze। -- धन्यवाद! –

+0

गतिशील यह वास्तव में उलझन में है जब यह अप्रत्याशित रूप से बदलता है, लेकिन यह वास्तव में उद्देश्य पर इसका उपयोग करते समय जावास्क्रिप्ट की सबसे शक्तिशाली सुविधाओं में से एक है। – timoxley

+0

हाँ, जावास्क्रिप्ट मुझे यह बेहद शक्तिशाली और भयानक संयुक्त रूप से अजीब खिंचाव देता है "ओह मेरे भगवान यह हास्यास्पद है।" - क्या कोई तरीका है कि आप कुछ सदस्यों को प्रोटोटाइप विधि का उपयोग करके निजी रखने की सलाह देंगे? –

2
User.prototype.login = function() { 
    var _this = this; 
    db.doDbStuff('get user data query', function(_error, _result) { 
     _this.username = _result[0].name; //this code will now work 
    }); 
} 

'this' आप का इस्तेमाल किया है अपने दायरे से बाहर था, यह कॉलबैक 'this' था।

12

एक अलग दृष्टिकोण के रूप में, मैं निम्नलिखित पैटर्न का प्रशंसक हूं।

 
module.exports = function User(data) { 

    //this properly private stuff. 

    var privateVar; 
    var username = data.username; 
    var pass = data.pass; //etc 

    function privateFunc() { 
    } 

    return { 
     login: function(cb) { 
      db.doStuff(username, pass, cb); 
     } 
    }; 
}; 
+4

मुझे यह भी पसंद है। लेकिन यह दृष्टिकोण केवल सिंगलेट के लिए काम करता है, है ना? आप इस तरह से तत्काल नहीं कर सकते हैं। – owzim

+2

@owzim यह पैटर्न वास्तव में केवल सिंगलेट के लिए नहीं है, यह मॉड्यूल.exports = (function() {...})() के समान दिखता है; जो एक एकल पैटर्न है क्योंकि यह फ़ंक्शन को तुरंत निष्पादित करता है। लेकिन इस उत्तर में कोड एक सिंगलटन नहीं है, क्योंकि अब आप ('डेटा') (my_instance_data) की आवश्यकता कर सकते हैं। MyInstanceFunction(); – Vegard

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