2010-07-07 10 views
11

मैं डगलस Crockfords Object.create विधि है जो मैं किसी को समझाने के लिए सक्षम हो सकता है आशा करती हूं कि के साथ एक विशेष लक्षण का सामना करना पड़ा: यदि मैं एक वस्तु बनानेजावास्क्रिप्ट Object.create इनहेरिट नेस्ट गुण

- कहते हैं ' व्यक्ति '- ऑब्जेक्ट शाब्दिक नोटेशन का उपयोग करके ऑब्जेक्ट.क्रेट का उपयोग एक नई ऑब्जेक्ट बनाने के लिए करें -' दूसरा पर्सन 'कहें - जो प्रारंभिक' व्यक्ति 'ऑब्जेक्ट से विधियों और गुणों को प्राप्त करता है।

यदि मैं फिर दूसरी ऑब्जेक्ट के नाम मानों को बदलता हूं - 'anotherPerson' - यह प्रारंभिक 'व्यक्ति' ऑब्जेक्ट का नाम मान भी बदलता है।

यह केवल तब होता है जब गुण नेस्ट कर रहे हैं, इस कोड को आप मैं क्या मतलब है की एक विचार देना चाहिए:

if (typeof Object.create !== 'function') { 
    Object.create = function (o) { 
     function F() {} 
     F.prototype = o; 
     return new F(); 
    }; 
}; 

// initiate new 'person' object 
var person = { 
    name: { 
     first: 'Ricky', 
     last: 'Gervais' 
    }, 
    talk: function() { 
     console.log('my name is ' + this.name.first + ' ' + this.name.last); 
    } 
} 

// create anotherPerson from person.prototype 
var anotherPerson = Object.create(person); 
// change name of anotherPerson 
anotherPerson.name.first = 'Stephen'; 
anotherPerson.name.last = 'Merchant'; 

// call talk method of both 'person' and 'anotherPerson' objects 
person.talk(); // oddly enough, prints 'Stephen Merchant' 
anotherPerson.talk(); // prints 'Stephen Merchant' 

अगर मैं घोंसले के बिना नाम मान संग्रहीत करने के लिए थे तो यह अजीब व्यवहार नहीं होती है - - उदाहरण के लिए

// initiate new 'person' object 
var person = { 
    firstName: 'Ricky', 
    lastName: 'Gervais', 
    talk: function() { 
     console.log('my name is ' + this.firstName + ' ' + this.lastName); 
    } 
} 

// create anotherPerson from person.prototype 
var anotherPerson = Object.create(person); 
// change name of anotherPerson 
anotherPerson.firstName = 'Stephen'; 
anotherPerson.lastName = 'Merchant'; 

// call talk method of both 'person' and 'anotherPerson' objects 
person.talk(); // prints 'Ricky Gervais' 
anotherPerson.talk(); // prints 'Stephen Merchant' 

इस घोंसले समस्या तब हो जब एक निर्माता समारोह और 'नए' कीवर्ड के साथ विरासत का एक शास्त्रीय शैली का उपयोग कर नहीं लगता है।

अगर कोई यह समझाने में सक्षम है कि ऐसा क्यों होता है तो मैं बहुत सराहना करता हूं !?

+2

संभावित डुप्लिकेट: [क्रॉकफोर्ड प्रोटोटाइप विरासत - नेस्टेड ऑब्जेक्ट्स के साथ समस्याएं] (http://stackoverflow.com/q/10131052/1048572) – Bergi

उत्तर

18

होता है ऐसा इसलिए है क्योंकि anotherPerson.name एक वस्तु है और यह प्रोटोटाइप श्रृंखला में ऊपरी संग्रहीत किया जाता है, मूल person वस्तु पर:

//... 
var anotherPerson = Object.create(person); 
anotherPerson.hasOwnProperty('name'); // false, the name is inherited 
person.name === anotherPerson.name; // true, the same object reference 

आप नव की name संपत्ति के लिए एक नया वस्तु बताए द्वारा इस से बच सकते हैं निर्मित ऑब्जेक्ट:

// create anotherPerson from person 
var anotherPerson = Object.create(person); 

anotherPerson.name = { 
    first: 'Stephen', 
    last: 'Merchant' 
}; 
+0

वाह, स्टैक ओवरफ़्लो फ़ोरम की तुलना में तत्काल मैसेंजर की तरह है! प्रतिक्रिया के लिए धन्यवाद, जो समझ में आता है - इसलिए दूसरे ऑब्जेक्ट में संदर्भ द्वारा नाम वस्तु है, वास्तव में इसकी प्रतिलिपि नहीं बनाई गई है। मैं मानता हूं कि मूल 'व्यक्ति' ऑब्जेक्ट का मूल्यांकन हैऑनप्रॉपर्टी ('नाम') === सच है क्योंकि यह 'अन्य पर्सन' का प्रोटोटाइप है। – Richard

+1

मैं जावास्क्रिप्ट में नया हूं, लेकिन मुझे लगता है कि आप इसका भी उपयोग कर सकते हैं: 'anotherPerson.name = Object.create (person.name);' वांछित अगर नया घोंसला ऑब्जेक्ट पुराने नेस्टेड ऑब्जेक्ट से प्राप्त होता है। –

+0

यह पहले से ही एक पुराना उत्तर है लेकिन मेरे पास अभी भी इसके लिए एक सवाल है। मैं समझता हूं कि बीनाम मौजूद नहीं है और यह एनाम खोजने के लिए चला जाता है, इस प्रकार यह एनाम के मान को प्रतिस्थापित करता है। हालांकि, दूसरे उदाहरण में, "बी फर्स्टनाम/आखिरी नाम" बी ऑब्जेक्ट में मौजूद है और ए के गुणों को ओवरराइड नहीं करता है? – user2734550

2

समस्या यह है कि ऑब्जेक्ट.क्रेट केवल एक उथली प्रतिलिपि करता है, गहरी प्रति नहीं, इसलिए person.name और anotherPerson.name दोनों एक ही ऑब्जेक्ट उदाहरण को इंगित करते हैं।

संपादित

हालांकि यह सच है कि person.name === anotherPerson.name, क्यों यह सच है के लिए मेरे स्पष्टीकरण ग़लत है। सही स्पष्टीकरण के लिए @ सीएमएस का जवाब देखें।

+2

सच है, दोनों एक ही उदाहरण को इंगित करते हैं, लेकिन वास्तव में, 'ऑब्जेक्ट.क्रेट' ऑब्जेक्ट कॉपी बिल्कुल नहीं बनाता है, यह सिर्फ एक नया * खाली ऑब्जेक्ट * बनाता है जो मूल से * विरासत * प्राप्त करता है। – CMS

+0

प्रतिक्रिया के लिए धन्यवाद। क्या आप उथले और गहरी प्रतिलिपि पर किसी भी सभ्य लेख के बारे में जानते हैं? – Richard

+0

@ सीएमएस, असल में 'एफ। प्रोोटोटाइप = ओ;' एक प्रति है। यह ऑब्जेक्ट और इसकी गुणों को नए ऑब्जेक्ट के प्रोटोटाइप के अंदर कॉपी करता है ... और कारण 'नाम' विशेषता कॉपी नहीं की जाती है क्योंकि जावास्क्रिप्ट में ऑब्जेक्ट अक्षर हमेशा संदर्भ होते हैं, इसलिए संदर्भ की प्रतिलिपि बनाई जाती है (इसकी सामग्री नहीं)। .. इसलिए ऐसा इसलिए नहीं है क्योंकि यह प्रोटोटाइप श्रृंखला में गहरा है या क्योंकि यह एक उथली प्रतिलिपि कर रहा है। –

1

कारण name विशेषता कॉपी नहीं है क्योंकि जावास्क्रिप्ट में वस्तु शाब्दिक हमेशा संदर्भ हैं, इसलिए संदर्भ कॉपी किया जाता है (न कि उसके सामग्री) ... इसलिए ऐसा इसलिए नहीं है क्योंकि यह प्रोटोटाइप श्रृंखला में गहरा है या क्योंकि यह एक उथली प्रतिलिपि कर रहा है।

+0

यह मुझे सही समझ में आता है .. क्या यह अभी भी सही है? – ryansstack

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