2012-02-16 11 views
8

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

var Parent = function() { 
    this.list = []; 
}; 

var Child = function() {}; 

Child.prototype = new Parent; 
Child.prototype.constructor = Child; 

var obj1 = new Child; 

obj1.list.push("hello"); 

console.log(obj1.list); // prints ["hello"]; 

जब मैं नई बाल वस्तु प्रारंभ obj1 को और बढ़ाने के लिए obj1.list एक मूल्य के साथ की कोशिश की (जनक जो सरणी चर सूची नामित शामिल विरासत) " हैलो ", obj1.list प्रिंट [" हैलो "] .. अब तक बहुत अच्छा है।

समस्या

आता है जब मैं ऊपर के उदाहरण से किया था और मैं तो धक्का obj2 के सूची एक मूल्य "अलविदा" के साथ obj2 करने के लिए नए बाल वस्तु प्रारंभ करने की कोशिश की, और obj2.list अब प्रिंट ["हैलो", "अलविदा"]। (नीचे दिए गए कोड :)

var obj2 = new Child; 

obj2.list.push("goodbye"); 

console.log(obj2.list); // prints ["hello", "goodbye"]; 

मैं एक गलत धारणा है यहाँ है, लेकिन सूची सरणी देखें जनक में किसी भी तरह मूल्य को बनाए रखना है और मैं पता नहीं क्यों।

यह एक बहुत बड़ी मुसीबत क्योंकि अगर मैंने उपरोक्त मामले की तरह जनक का पुन: उपयोग कई अन्य बच्चे कक्षाओं में वर्ग, अगर जनक सरणी चर अपने बच्चे कक्षाओं के लिए साझा किया है, मूल्य अन्य बच्चे को साझा किया जाएगा है कक्षाएं भी, जो मेरे लिए अप्रत्याशित है।

मेरी अपेक्षा ही जब बाल वर्ग obj1, तो जो जब मैं नई बालobj2 करने के लिए वस्तु प्रारंभ करने में आरंभ नहीं हो जाता जनक वर्ग को जाता है बाल वर्ग नई वस्तु का प्रतिनिधित्व करता है,, obj1 से धक्का मूल्य obj2 के साथ साझा नहीं किया जाना चाहिए।

- प्रश्न -

किसी को भी मुझे यह पता लगाने क्यों सूची उदाहरण में (जनक की सरणी चर) ऊपर मूल्यों को बरकरार रखे हुए मदद कर सकते हैं/मूल्यों कि बाल द्वारा आरंभ किया जाता का हिस्सा ऑब्जेक्ट्स (उपरोक्त मामले में, obj1 और obj2)?

यदि आपके पास कोई अन्य समाधान है जो इस समस्या को हल कर सकता है, तो यह आपके लिए बहुत अच्छा होगा, लेकिन मुझे पहले समस्या को हल करने में खुशी होगी।

+0

क्योंकि दोनों उदाहरण एक ही 'माता-पिता' उदाहरण को उनके प्रोटोटाइप के रूप में संदर्भित करते हैं और इसलिए एक ही सरणी में। यहां कई जावास्क्रिप्ट ओओपी प्रश्न हैं, आपको उन्हें देखना चाहिए। –

+0

[संभावित रूप से जावास्क्रिप्ट के ओओपी को पूर्ववत करने के उदाहरण: संभावित उदाहरणों को संशोधित करने के उदाहरण] (http://stackoverflow.com/questions/4541788/undesrtanding-javascripts-oop-instances-modifying-other-instances) और [जावास्क्रिप्ट प्रोटोटाइप प्रॉपर्टी अपेक्षित के रूप में काम नहीं कर रही है) सरणी और ऑब्जेक्ट फ़ील्ड के साथ] (http://stackoverflow.com/questions/8230085/javascript-prototype-property-not-working-as-expected-with-array-and-object-fiel) –

उत्तर

12

जब किसी बच्चे के ऑब्जेक्ट में प्रोटोटाइप ऑब्जेक्ट से विरासत में प्राप्त संपत्ति होती है, तो वास्तव में क्या हो रहा है कि बच्चे के पास संदर्भ प्रोटोटाइप में है, जिसमें संपत्ति शामिल है। बच्चे की अपनी प्रतिलिपि नहीं है।तो दोनों बच्चे एक ही सरणी   — पर उपयोग कर रहे हैं (0) Parent प्रोटोटाइप ऑब्जेक्ट जिसे आपने Child.prototype पर असाइन किया है।

पहले कुछ चित्र, फिर अधिक टेक्स्ट। इस :-)

new Parent() आप देता है:

+-----------------+ 
| Parent instance | 
+-----------------+ 
| list = []  | 
+-----------------+

... जो आप तो Child.prototype को आवंटित।

फिर, new Child() आप देता है यह:

+------------------+ 
| Child instance 1 | 
+------------------+  +-----------------+ 
| (prototype)  |------->| Parent instance | 
+------------------+  +-----------------+ 
          | list = []  | 
          +-----------------+

new Child() कर फिर से आप एक दूसरे से मिलते हैं:

 
+------------------+  +------------------+ 
| Child instance 1 |  | Child instance 2 | 
+------------------+  +------------------+ 
| (prototype)  |---+ | (prototype)  |---+ 
+------------------+ | +------------------+ | 
         |       | 
         |       |  +-----------------+ 
         +-------------------------+---->| Parent instance | 
                 +-----------------+ 
                 | list = []  | 
                 +-----------------+

तो जैसा कि आप देख सकते हैं, Child उदाहरणों के सभी साझा कर रहे हैं ही Parent उदाहरण (उनके प्रोटोटाइप), जिस पर एक सरणी है।

आप जब कहते हैं:

var obj = new Child(); 
obj.list.push("foo"); 

... यहाँ JavaScript इंजन जब यह obj.list देखता है क्या करता है:

  1. अगर obj अपने खुद संपत्ति list कहा जाता है को देखने के लिए लग रहा है। यदि नहीं, तो:
  2. यह देखने के लिए लगता है कि obj के प्रोटोटाइप में संपत्ति list कहलाती है। यदि नहीं, तो:
  3. यह देखने के लिए लगता है कि obj के प्रोटोटाइप के प्रोटोटाइप में संपत्ति list कहलाती है।
  4. आदि जब तक हम प्रोटोटाइप से बाहर नहीं निकलते।

आपके मामले में, obj के बाद से अपने खुदlist संपत्ति नहीं है, इंजन अपने प्रोटोटाइप (Parent उदाहरण आप Child.prototype को सौंपना), जो इस मामले में करता है संपत्ति के लिए लग रहा है। तो एक का उपयोग किया जाता है। यह बच्चे या कुछ भी प्रतिलिपि नहीं है, यह का उपयोग किया गया है। और निश्चित रूप से, चूंकि यह एक सरणी है, इसलिए सरणी पर कुछ दबाकर वास्तव में इसे सरणी पर धक्का देता है।

यदि आप obj.list करने के लिए असाइन कुछ थे, तो obj अपने खुदlist संपत्ति मिलेगा, चेन तोड़ने। इसलिए this.list = [];Child में प्रत्येक बच्चे को अपनी सूची देगी।

आप इसे किसी भी समय प्रोटोटाइप पर ऑब्जेक्ट संदर्भ पर देखेंगे, जहां ऑब्जेक्ट एक प्रकार है जिसे संशोधित किया जा सकता है (एक "mutable" ऑब्जेक्ट)। Arrays, तिथियां, सादे वस्तुओं ({}), RegExps, आदि, वे सभी राज्य हैं और वे सभी संशोधित किया जा सकता है, तो आप इसे उनके साथ देखेंगे।(String उदाहरण अपरिवर्तनीय हैं, इसलिए यद्यपि यह वही होता है, आपको इससे कोई प्रभाव नहीं दिखता है क्योंकि स्ट्रिंग को बदला नहीं जा सकता है।)

प्राइमेटिव के साथ, हालांकि आप उन्हें प्राप्त करते हैं, आप अपना राज्य नहीं बदल सकते हैं (आप केवल को एक अलग राज्य के साथ एक नए आदिम के साथ प्रतिस्थापित कर सकते हैं), इसलिए आपको यह वही प्रभाव दिखाई नहीं देता है। इसलिए यदि obj संपत्ति को foo अपने प्रोटोटाइप से प्राप्त करता है, और foo42 है, alert(obj.foo) प्रोटोटाइप से मूल्य प्राप्त करेगा और "42" दिखाएगा। foo बदलने का एकमात्र तरीका obj.foo = 67 या इसी तरह   — जो obj अपने खुदfoo की प्रति, प्रोटोटाइप की प्रतिलिपि से अलग कर देता है कहने के लिए है। (यह सच है भले ही आप ++ और -- जैसी चीजों का उपयोग करें, उदाहरण के लिए ++obj.foo; वास्तव में obj.foo = obj.foo + 1 के रूप में मूल्यांकन किया जाता है)।

+5

आपका भयानक असीसी ग्राफिक्स वारंट अधिक +1 से, लेकिन यह सब मुझे –

+0

इनाम देने की अनुमति है मुझे कुछ ASCII-art से प्यार है। ;-) –

+0

सहमत! ASCII-art के लिए +1। – pete

3

जो चीज़ आप यहां गायब हैं, वह है कि Parent.list केवल एक बार तत्काल हो रहा है; जब आप अपने 'प्रोटोटाइप को Child.prototype में कॉपी करते हैं।

जावास्क्रिप्ट में "सबक्लास" को इंस्टेंट करने से स्वचालित रूप से पैरेंट कन्स्ट्रक्टर का आह्वान नहीं करता है। इस प्रकार, Child के सभी उदाहरण सरणी के समान उदाहरण साझा करेंगे।

Child के निर्माता को संशोधित करना माता-पिता निर्माता आह्वान करने के लिए इलाज आप अपनी बीमारी के लिए तलाश किया जाना चाहिए:

var Child = function() { 
    Parent.call(this); 
}; 

जाहिर है आप पहले से ही इस विषय पर कुछ ज्ञान है, लेकिन अगर आप रुचि रखते हैं, यहाँ एक है पढ़ने विषय पर कुछ ग्रंथों के लायक:

+0

धन्यवाद nikc! ईमानदारी से, आपका नमूना कोड वह है जो वास्तव में इस दूसरी समस्या को हल करता है। मैं उपयोग करना भूल गया। कॉल जो मुझे इस सवाल पर ले जाता है। –

+0

धन्यवाद, नमूना कोड भी मेरे लिए बेहद उपयोगी था! –

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