2011-08-21 14 views
17

के साथ जावास्क्रिप्ट नेमस्पेस घोषणा मुझे पता है, यह अक्सर चर्चा की जाती है। लेकिन 1 9वीं शताब्दी में से किसी की तरह चारों ओर खोज करने के बाद, मुझे कुछ सलाह चाहिए। मुझे "नेमस्पेस" घोषित करके कोई समस्या नहीं है, लेकिन जब प्रोटोटाइप.फू फ़ंक्शन की बात आती है, तो मैं अटक गया। मैं एक रास्ता मिल गया, लेकिन मैं इसे पसंद नहीं है:फ़ंक्शन-प्रोटोटाइप

Namespace = { 
    obj: function() { 
     this.foo="bar"; 
    }, 
    obj.prototype.start: function(tabinst) { 
     this.foo="fubar"; 
    } 
} 
... 

:

Namespace = {} 
Namespace.obj = function() { 
    this.foo="bar"; 
} 
Namespace.obj.prototype.start = function() { 
    this.foo="fubar"; 
} 

blah = new Namespace.obj(); 
blah.start(); 

अब, के बाद से मैं एक छोटे से पटकथा के मामले में विक्षिप्त हूँ, मैं कुछ इस तरह करना चाहते हैं लेकिन फिर यह एक त्रुटि फेंकता है: "अनकही सिंटेक्स त्रुटि: अप्रत्याशित टोकन।"

मुझे पता है, यह कॉस्मेटिक है, लेकिन मुझे लगता है कि एक वर्ग और प्रोटोटाइप कार्यों वाले "नेमस्पेस" को घोषित करने का एक बेहतर तरीका होना चाहिए।

उत्तर

29

जिस तरह से मैं इसे करूँगा "Module pattern" का उपयोग कर रहा है।
आप मूल रूप से अपने सभी "मॉड्यूल" तर्क को स्वयं निष्पादन फ़ंक्शन में समाहित करते हैं जो आपके वर्ग, फ़ंक्शंस, चर आदि वाले ऑब्जेक्ट को वापस कर देगा ... आपके मॉड्यूल एपीआई को उजागर करने के रूप में वापसी मूल्य के बारे में सोचें।

Namespace = (function() { 
    /** Class obj **/ 
    var obj = function() { 
     this.foo = 'bar'; 
    }; 
    obj.prototype = { 
     start: function() { 
      this.foo = 'fubar'; 
     } 
    }; 

    /** Class obj2 **/ 
    var obj2 = function() { 
     this.bar = 'foo' 
    }; 
    obj2.prototype = { 
     start: function() { 
      this.bar = 'barfoo'; 
     }, 
     end: function() { 
      this.bar = ''; 
     } 
    }; 
    return { 
     obj : obj, 
     obj2: obj2 
    }; 
})(); 

var o = new Namespace.obj() 
o.start() 

आगे "obj" वर्ग के तरीकों को संपुटित करने के लिए और निर्माता हम कर सकता है में निम्नलिखित:

/** Class obj **/ 
var obj = (function() { 
    /** class Constructor **/ 
    var obj = function() { 
     this.foo = 'bar'; 
    }; 
    /** class methods **/ 
    obj.prototype = { 
     start: function() { 
      this.foo = 'fubar'; 
     } 
    }; 
    return obj; 
})(); 

भी एक महत्वपूर्ण विशेषता यह है कि इस पद्धति का उपयोग कर मुक्त करने के लिए आता है, जो "नहीं है

/** Class Foo **/ 
var Foo = (function() { 
    // Private variables 
    var private_number = 200 
    /** class Constructor **/ 
    var Foo = function() { 
     this.bar = 0; 
    }; 
    /** class methods **/ 
    Foo.prototype = { 
     add: function() { 
      this.bar += private_number; 
     } 
    }; 
    return Foo; 
})(); 

foo = new Foo(); 
alert(foo.bar); // 0 
foo.add(); 
alert(foo.bar);// 200 
alert(foo.private_number) //undefined 
+0

अच्छा दृष्टिकोण, +1। – Jiri

+0

थान अमजद, यह बहुत अच्छा है। लेकिन अब मैं फिर से ठोकर खा रहा हूँ। क्या मैं इसे सही देखता हूं: इस दृष्टिकोण के साथ एक नेमस्पेस.ब्लैह() फ़ंक्शन बनाना संभव नहीं है जो पृथक रूप ओबीजे है? –

+2

@ जॉनी अगर मैं आपके प्रश्न को सही समझता हूं, तो वापसी ऑब्जेक्ट में 'blah' फ़ंक्शन जोड़ें: '। । वापसी; ' –

2

हाँ, क्योंकि, आप एक वस्तु घोषणा

obj.prototype या यहाँ obj.something में चेनिंग के इस प्रकार का उपयोग नहीं कर सकते क्योंकि भाषा एक गैर वस्तु मूल्य के रूप में obj देखता है। वाह, मैंने अभी देखा है कि क्या मैंने कहा प्रश्न के भीतर पहले से ही था: आप इस

Namespace = {}; 

Namespace.obj =function() { 
     this.foo="bar"; 
}; 

Namespace.obj.prototype.start = function(tabinst) { 
     this.foo="fubar"; 
}; 

console.log(Namespace.obj.prototype); 

की तरह एक प्रभाव नकली कर सकते हैं

संपादित (इस बेला http://jsfiddle.net/WewnF/ देखें)। मुझे बहुत खेद है कि जल्द ही यह नहीं देखा ... वैसे जिस तरह से आपने स्वयं को वर्णित किया है वह इसे प्राप्त करने का सही तरीका है।

अन्यथा आप इस तरह अपना कोड फिर से लिख सकते हैं - लेकिन यह ठीक नहीं है कि आप इसके बाद क्या कर रहे हैं और यह काम नहीं करेंगे (क्योंकि ओबीजे एक कार्य नहीं होगा और आपको इसका मुख्य कार्य कॉल करना होगा इस obj.main() की तरह;)

Namespace = { 
    obj: { 
      main : function() { 
       this.foo="bar"; 
      }, 
      prototype : { 
      start: function(tabinst) { 
      this.foo="fubar"; 
      } 
      } 
    } 
} 

संपादित करें 2: इस बेला http://jsfiddle.net/NmA3v/1/

Namespace = { 
    obj: function() { 
     this.foo="bar"; 
    }, 
    prototype: { 
     obj : { 
      start : function(hi) { 
       alert(hi); 
      } 
     } 

    }, 

    initProto : function(){ 
     for(var key in Namespace) 
     { 
      if(key !== "prototype") 
      { 
       for(var jey in Namespace.prototype[ key ]) 
        Namespace[ key ].prototype[ jey ] = Namespace.prototype[ key ][ jey ]; 
      } 
     } 
    } 
} 

Namespace.initProto(); 

console.log(Namespace.obj); 

var test = new Namespace.obj(); 

test.start("Hello World"); 

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

फिर namespace.protoInit() के साथ, हम सभी गुणों के माध्यम से पुनरावृत्त करते हैं - और नामस्थान.प्रोटोटाइप [कुंजी] से कार्यों को निकालें और उन्हें नामस्थान [कुंजी] .prototype में जोड़ें - सफलतापूर्वक प्रोटोटाइप ऑब्जेक्ट को विस्तारित करना! थोड़ा अपरंपरागत, लेकिन काम करता है!

+0

आपके संपादन में पहला स्निपेट आपके विचार में पहला स्निपेट काम नहीं करेगा जैसा कि आप सोच सकते हैं। 'obj.main' और' obj.prototype' दो अलग-अलग स्वतंत्र कार्य हैं। हां, 'यह' उसी ऑब्जेक्ट को संदर्भित करेगा यदि आप उन्हें 'नया' के बिना बुलाते हैं, लेकिन केवल इसलिए कि यह 'विंडो' को संदर्भित करता है। तो आप 'foo' वैश्विक बना देंगे। –

+0

आपका दूसरा उदाहरण 'नेमस्पेस' को केवल एक "वर्ग" तक सीमित करता है जो किसी भी तरह से नामस्थान के उद्देश्य को हरा देता है। –

+0

आप पहले उदाहरण के लिए सही हैं, और मैं इसे जल्द से जल्द नहीं देख पा रहा हूं, लेकिन मैं दूसरे के बारे में असहमत हूं। यह केवल एक "वर्ग" तक सीमित क्यों है? यदि आप अधिक ऑब्जेक्ट्स का उपयोग करते हैं, तो यह उनके माध्यम से पुन: सक्रिय होगा और उन्हें सही प्रोटोटाइप मानों को असाइन करेगा। – Pantelis

3

बस किक के लिए और इसके बाद के संस्करण जवाब पर विस्तार करने के लिए: निजी चर ", निम्नलिखित पर विचार करें। नेस्टेड नेमस्पेस

var NS = {}; 

// Class List 
NS.Classes = { 
    Shape: (function(){ 
    // Private 
    var whateveryouwishboss = false; 

    // Public 
    var Shape = function(x,y,w,h){ 
     this.x = x; 
     this.y = y; 
     this.w = w; 
     this.h = h; 
    }; 
    Shape.prototype = { 
     draw: function(){ 
     //... Im on prototype Shape 
     } 
    } 
    return Shape; 
    })(), 
    Person: (function(){ 
    //.... 
    })() 
} 

/////// Let the games begin 

var rect = new NS.Class.Shape(0,0,10,10); 
rect.draw()