2013-02-06 36 views
7

हम इस बात पर बहस कर रहे हैं कि हमारे जेएस ऐप में ऑब्जेक्ट्स को कैसे संभालना है, स्टॉयन स्टीफानोव की पुस्तक का अध्ययन करना, 'नया', 'यह', 'प्रोटोटाइप', बंद आदि पर अंतहीन एसओ पोस्ट पढ़ना। (तथ्य कि बहुत सारे हैं, और उनके पास इतने सारे प्रतिस्पर्धी सिद्धांत हैं, सुझाव देते हैं कि कोई स्पष्ट जवाब नहीं है)।कोडिंग जावास्क्रिप्ट की इस शैली के साथ क्या गलत है? (बंद बनाम प्रोटोटाइप)

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

इस को देखते हुए, क्या (ओओ शैली और इतिहास के दशकों को अस्वीकार करने के अलावा) इस तकनीक के साथ गलत होगा?

// namespace to isolate all PERSON's logic 
var PERSON = {}; 

// return an object which should only ever contain data. 
// The Catch: it's 100% public 

PERSON.constructor = function (name) { 
    return { 
     name: name 
    } 
} 

// methods that operate on a Person 
// the thing we're operating on gets passed in 

PERSON.sayHello = function (person) { 
    alert (person.name); 
} 

var p = PERSON.constructor ("Fred"); 
var q = PERSON.constructor ("Me"); 

// normally this coded like 'p.sayHello()' 
PERSON.sayHello(p); 
PERSON.sayHello(q); 
जाहिर

:

  1. अपवित्र मायनों में 'पी' परिवर्तनशील से किसी को रोकने के लिए कुछ, या बस व्यक्ति हर जगह फैल समाप्त के तर्क वहाँ होगा। (यह कैननिकल 'नई' तकनीक के साथ भी सच है)।
  2. प्रत्येक फ़ंक्शन में 'पी' पास करने में मामूली परेशानी होगी जो आप इसका उपयोग करना चाहते थे।
  3. यह अजीब दृष्टिकोण है।

लेकिन क्या इसे खारिज करने के लिए पर्याप्त अच्छे कारण हैं? सकारात्मक पक्ष पर:

  1. यह कुशल के रूप में (बेशक) दोहराव समारोह घोषणा के साथ बंद करने का विरोध किया है।
  2. ऐसा लगता है कि बहुत सरल और समझा जा सकता है, 'यह' हर जगह के साथ झुकाव के विपरीत।

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

+0

क्या इस दृष्टिकोण के साथ कोई व्यक्ति निर्माता है? बस बतख-टाइपिंग 'PERSON.sayHello ({name: "फ्रेड"} का उपयोग करें) ' – house9

+0

जेएस -1 के साथ मेरे पसंदीदा दृष्टिकोण) कॉफ़ीस्क्रिप्ट का उपयोग करें, सभी का इलाज नहीं, बल्कि ओओ कक्षाओं के भ्रम को देता है - 2) कार्यात्मक कन्स्ट्रक्टर टेम्पलेट" जावास्क्रिप्ट: द गुड पार्ट्स "पृष्ठ 52 - http://www.amazon.com/JavaScript- गुड- पर्ट्स- डगलस- क्रॉकफोर्ड/डीपी/056517742 – house9

+0

@ हाउस 9 लेकिन एक इलाज-सब कुछ क्या है? कक्षाएं सिर्फ वाक्यविन्यास और वाक्यविन्यास हैं जो उस पर एक पूर्व संकलित प्रतिमान में अधिक समझ में आता है। जेएस सीखने की कोशिश करते समय लोग इतने लटका क्यों देते हैं? जेएस को समझने की कुंजी जेएस कार्यों को समझ रही है। उसके बाद रचनाकार बच्चे के खेल होते हैं। ओओपी के जेएस के दृष्टिकोण के बारे में कुछ भी नहीं टूटा है। पूर्व में संकलित भाषाओं की तुलना में जेएस में किसी भी ओओपी उन्मुख पैटर्न को रिग करने के लिए बहुत कम कोड का नरक लगता है। –

उत्तर

8

इसमें कुछ भी गलत नहीं है। लेकिन जावास्क्रिप्ट की प्रोटोटाइप प्रणाली का उपयोग करने में निहित कई फायदे हैं।

  • आपका ऑब्जेक्ट किसी अन्य वस्तु के बारे में कुछ भी नहीं जानता है, यह एक वस्तु शाब्दिक है। तो instanceof आपकी उत्पत्ति की पहचान करने में आपकी सहायता नहीं करेगा। आप केवल बतख टाइपिंग का उपयोग करके फंस जाएंगे।
  • आपकी विधियां अनिवार्य रूप से नामांकित स्थैतिक कार्य है, जहां आपको ऑब्जेक्ट को पहले तर्क के रूप में पास करके स्वयं को दोहराना होगा। प्रोटोटाइप ऑब्जेक्ट करके, आप डायनामिक प्रेषण का लाभ ले सकते हैं, ताकि p.sayHello()PERSON या ANIMAL के लिए अलग-अलग चीजें कर सकें, जिस प्रकार जावास्क्रिप्ट के बारे में पता है। यह पॉलिमॉर्फिज्म का एक रूप है। जब भी आप किसी विधि को कॉल करते हैं, तो आपके दृष्टिकोण के लिए आपको नाम (और संभावित रूप से गलती करने) की आवश्यकता होती है।
  • आपको वास्तव में constructor फ़ंक्शन की आवश्यकता नहीं है, क्योंकि फ़ंक्शंस पहले से ही ऑब्जेक्ट्स हैं।आपका PERSON वैरिएबल कन्स्ट्रक्टर फ़ंक्शन भी हो सकता है।

आपने जो किया है वह मॉड्यूल पैटर्न (नामस्थान की तरह) बना रहा है।

यहाँ एक और पैटर्न है रहता है कि तुम क्या है, लेकिन इसके बाद के संस्करण फायदे की आपूर्ति:

function Person(name) 
{ 
    var p = Object.create(Person.prototype); 
    p.name = name; // or other means of initialization, use of overloaded arguments, etc. 
    return p; 
} 
Person.prototype.sayHello = function() { alert (this.name); } 

var p = Person("Fred"); // you can omit "new" 
var q = Person("Me"); 
p.sayHello(); 
q.sayHello(); 
console.log(p instanceof Person); // true 
var people = ["Bob", "Will", "Mary", "Alandra"].map(Person); 
     // people contains array of Person objects 
+0

मैं जल्द ही स्वीकार नहीं करने के लिए क्षमा चाहता हूं, उत्कृष्ट उत्तरों के लिए बहुत बहुत धन्यवाद। चीयर्स! – GregT

1

हाँ, मैं वास्तव में नहीं समझ रहा हूँ तुम क्यों चकमा करने के लिए निर्माता दृष्टिकोण कोशिश कर रहे हैं या क्यों वे यहाँ तक कि एक महसूस किया फंक्शन कन्स्ट्रक्टर (ऑब्जेक्ट.क्रेट और जल्द ही कक्षाओं) पर सिंटैक्टिकल शुगर की आवश्यकता होती है जब स्वयं द्वारा कन्स्ट्रक्टर ओओपी के लिए एक सुरुचिपूर्ण, लचीला और पूरी तरह से उचित दृष्टिकोण हैं, इससे कोई फर्क नहीं पड़ता कि क्रॉकफोर्ड जैसे लोगों को उन्हें पसंद नहीं है (क्योंकि लोग नए कीवर्ड का उपयोग करना भूल जाते हैं - गंभीरता से?)। जेएस भारी कामकाजी है और इसकी ओओपी यांत्रिकी अलग नहीं हैं। आईएमओ से छिपाने से इसे गले लगाने के लिए बेहतर है।

सबसे पहले, "जाहिर"

  1. शायद ही और भी जावास्क्रिप्ट में उल्लेख के लायक के तहत सूचीबद्ध अपने अंक। उत्परिवर्तन की उच्च डिग्री डिजाइन द्वारा है। हम जावास्क्रिप्ट में खुद या अन्य डेवलपर्स से डरते नहीं हैं। निजी बनाम सार्वजनिक प्रतिमान उपयोगी नहीं है क्योंकि यह हमें मूर्खता से बचाता है बल्कि इसलिए कि यह अन्य देव के कोड के पीछे इरादे को समझना आसान बनाता है।

  2. invoking में प्रयास समस्या नहीं है। परेशानी बाद में आती है जब यह स्पष्ट नहीं होता कि आपने वहां क्या किया है। मैं वास्तव में नहीं देखता कि आप यह हासिल करने की कोशिश कर रहे हैं कि कोर भाषा दृष्टिकोण आपके लिए बेहतर नहीं है।

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

अब के तहत अपने अंक "सकारात्मक पक्ष," सभी की

  1. पहले, दोहराव समारोह परिभाषा वास्तव में केवल भारी पाशन परिदृश्य में के बारे में चिंता करने के लिए कुछ था। यदि आप नियमित रूप से बड़ी मात्रा में ऑब्जेक्ट्स का उत्पादन कर रहे थे, तो गैर-प्रोटोटाइप वाली सार्वजनिक विधि परिभाषाओं के लिए एक पेर्फ समस्या होने के लिए पर्याप्त तेज़ी से पर्याप्त मात्रा में उत्पादन होता है, तो संभवतः आप बिना किसी क्रम में गैर-तुच्छ वस्तुओं के साथ स्मृति उपयोग समस्याओं में भाग ले रहे होंगे। मैं पिछले काल में बात करता हूं, हालांकि, क्योंकि यह वास्तव में किसी भी तरह से एक प्रासंगिक मुद्दा नहीं है। आधुनिक ब्राउज़रों में, अन्य कार्यों के अंदर परिभाषित फ़ंक्शंस वास्तव में आधुनिक जेआईटी कंपाइलर्स के काम के कारण आम तौर पर प्रदर्शन को बढ़ाते हैं। चाहे आप कौन से ब्राउज़र का समर्थन करते हैं, भले ही प्रति ऑब्जेक्ट परिभाषित कुछ funcs एक गैर-मुद्दा है जब तक कि आप हजारों ऑब्जेक्ट्स की अपेक्षा न करें।

  2. सरल और समझने योग्य के सवाल पर, यह मेरे लिए नहीं है क्योंकि मुझे नहीं पता कि आपने यहां क्या जीत हासिल की है।अब एक ऑब्जेक्ट का उपयोग करने के बजाय, मुझे ऑब्जेक्ट और इसके छद्म-कन्स्ट्रक्टर दोनों का एक साथ उपयोग करना होगा, यदि मैं परिभाषा को नहीं देख रहा था तो मुझे उस क्रिया का संकेत मिलेगा जिसका उपयोग आप वस्तुओं को बनाने के लिए 'नए' कीवर्ड के साथ करते हैं । अगर मैं आपके कोडबेस में नया था तो मैं यह समझने की कोशिश कर रहा था कि आपने ऐसा कुछ और चिंता तोड़ने से बचने के लिए क्यों किया है, जिसे मैं समझ नहीं पाया।

मेरे सवालों का होगा:

क्यों न सिर्फ पहली जगह में वस्तु में सभी तरीकों निर्माता में शाब्दिक जोड़ सकता हूँ? वहां कोई प्रदर्शन समस्या नहीं है और वास्तव में कभी भी ऐसा नहीं हुआ है, इसलिए एकमात्र अन्य संभावित जीत यह है कि आप इसके साथ नई वस्तुओं को बनाने के बाद व्यक्ति को नए तरीकों को जोड़ने में सक्षम होना चाहते हैं, लेकिन यही है कि हम उचित रचनाकारों के लिए प्रोटोटाइप का उपयोग करते हैं (प्रोटोटाइप विधियों बीटीडब्ल्यू पुराने ब्राउज़र में स्मृति के लिए बहुत अच्छे हैं क्योंकि उन्हें केवल एक बार परिभाषित किया जाता है)।

और यदि आपको यह जानने के तरीकों के लिए वस्तु को पास करना है कि गुण क्या हैं, तो आप वस्तुओं को क्यों चाहते हैं? क्यों न केवल उन कार्यों को सरल डेटा संरचना-प्रकार की वस्तुओं की अपेक्षा करते हैं जो कुछ गुणों के साथ हैं? यह वास्तव में अब ओओपी नहीं है।

लेकिन मेरी आलोचना

आप OOP का मुख्य बिंदु जो कुछ जावास्क्रिप्ट अधिकांश भाषाओं की तुलना में लोगों से छुपा नहीं करने का एक बेहतर काम करता है है भूल रहे हैं का मुख्य बिंदु।

function Person(name){ 
    //var name = name; //<--this might be more clear but it would be redundant 
    this.identifySelf = function(){ alert(name); } 
} 

var bob = new Person(); 
bob.identifySelf(); 

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

उत्तरदायित्व का स्पष्ट विभाजन कुंजी

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

तो चलो कहते हैं कि कुछ उत्पादन के साथ त्रुटि हुई है करते हैं:

  • हमारे कार्यों का सख्ती से प्रक्रियात्मक ढेर में हाथ की संख्या है कि डेटा में गड़बड़ हो सकता है करने के लिए कोई वास्तविक सीमा नहीं है। हमारे पास अच्छी त्रुटि-होल्डिंग हो सकती है लेकिन एक फ़ंक्शन इस तरह से शाखा बना सकता है कि मूल अपराधी को ट्रैक करना मुश्किल है।

  • उचित ओओपी डिज़ाइन में जहां डेटा आमतौर पर ऑब्जेक्ट गेटकीपर के पीछे होता है, मुझे पता है कि केवल एक वस्तु वास्तव में परिवर्तन को जिम्मेदार बना सकती है।

अधिकांश समय उनके सभी डेटा को उजागर करने वाले ऑब्जेक्ट्स पुराने प्रक्रियात्मक दृष्टिकोण से वास्तव में केवल मामूली बेहतर हैं।जो वास्तव में करता है वह आपको कम से कम संबंधित तरीकों को वर्गीकृत करने का नाम देता है।

बहुत हलचल के बारे में 'इस'

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

  • इसे परिभाषित किया गया है और एक उदाहरण की संपत्ति के रूप में जाना जाता है।

  • इसे एक ईवेंट हैंडलर के रूप में पारित किया गया है (जो इसे सुनवाई की बात के सदस्य के रूप में बुलाएगा)।

  • आप किसी अन्य ऑब्जेक्ट की संपत्ति के रूप में अस्थायी रूप से इसे निर्दिष्ट किए बिना कॉल या लागू विधियों का उपयोग कर रहे हैं।

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

+0

उत्कृष्ट प्रतिक्रिया के लिए बहुत बहुत धन्यवाद। चियर्स – GregT