दिलचस्प पोस्ट
JDBC और MySQL के साथ एक "संचार लिंक विफलता" सुलझाना जहां क्लॉज में स्ट्रिंग्स की सूची बनाने के लिए कॉमा से अलग स्ट्रिंग पार्स करें जावा मेमोरी लीक को हल करने के लिए सामान्य रणनीति? सी # (.नेट 2.0) में विंडोज के लिए इंटरप्रोसेस कम्यूनिकेशन एक मोनद क्या है? जावास्क्रिप्ट फाइलों के लिए पैरामीटर पास करना JFrames के बीच मूल्यों को पास करना जावा में हैश कोड () स्ट्रिंग में एक गुणक के रूप में 31 का उपयोग क्यों करता है? जोड़ जावास्क्रिप्ट में काम नहीं कर रहा है अजगर में द्विआधारी को पूर्णांक परिवर्तित करना विंडोज सर्विस बनाम शेड्यूल्ड कार्य एंड्रॉइड स्टूडियो – एंड्रॉइड एसडीके पथ को कैसे बदलें Math.round (0.49999999999999994) क्यों वापस 1? लिनक्स में पर्यावरण चर LD_LIBRARY_PATH कैसे सेट करें Uncaught सिंटेक्स त्रुटि: JSON.parse के साथ अनपेक्षित टोकन

क्रॉकफोर्ड का प्रोटोटाइप उत्तराधिकार – नेस्टेड ऑब्जेक्ट्स के साथ समस्याएं

मैं डगलस क्रॉकफोर्ड द्वारा "जावास्क्रिप्ट: द गुड पार्ट्स" पढ़ रहा हूं – और जब यह थोड़ी सी चरम है, तो मैं उसके बारे में बहुत कुछ कहना चाहता हूं।

अध्याय 3 में, वह ऑब्जेक्ट्स पर चर्चा करता है और एक समय में "नया" कीवर्ड के उपयोग के साथ आने वाले कुछ भ्रम / मुद्दों से बचने और इसे पारित करने के लिए एक समय पर एक पैटर्न ( यहां भी पाया गया ) देता है।

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

इसलिए मैंने इस पर एक प्रोजेक्ट पर काम करने की कोशिश की है, और नेस्टेड वस्तुओं से वारिस करने का प्रयास करते समय मैंने एक समस्या देखी। अगर मैं इस पद्धति का इस्तेमाल करते हुए नेस्टेड ऑब्जेक्ट के मान को अधिलेखित करता हूं, तो यह प्रोटोटाइप श्रृंखला के सभी तरीकों से नेस्टेड तत्व को अधिलेखित करता है।

flatObj का उदाहरण निम्नलिखित उदाहरण में flatObj तरह है, जो अच्छी तरह से काम करता है। व्यवहार, हालांकि, नेस्टेड ऑब्जेक्ट के साथ असंगत है:

 var flatObj = { firstname: "John", lastname: "Doe", age: 23 } var person1 = Object.create(flatObj); var nestObj = { sex: "female", info: { firstname: "Jane", lastname: "Dough", age: 32 } } var person2 = Object.create(nestObj); var nestObj2 = { sex: "male", info: { firstname: "Arnold", lastname: "Schwarzenneger", age: 61 } } var person3 = { sex: "male" } person3.info = Object.create(nestObj2.info); // now change the objects: person1.age = 69; person2.info.age = 96; person3.info.age = 0; // prototypes should not have changed: flatObj.age // 23 nestObj.info.age // 96 ??? nestObj2.info.age // 61 // now delete properties: delete person1.age; delete person2.info.age; delete person3.info.age; // prototypes should not have changed: flatObj.age // 23 nestObj.info.age // undefined ??? nestObj2.info.age // 61 

(एक बेला पर भी)

क्या मैं कुछ गलत कर रहा हूं, या क्या इस पद्धति की एक सीमा है?

वेब के समाधान से एकत्रित समाधान "क्रॉकफोर्ड का प्रोटोटाइप उत्तराधिकार – नेस्टेड ऑब्जेक्ट्स के साथ समस्याएं"

कोई विसंगति नहीं है बस नेस्टेड ऑब्जेक्ट्स के बारे में मत सोचो: किसी ऑब्जेक्ट की सीधी संपत्ति हमेशा अपने प्रोटोटाइप या खुद की संपत्ति पर होती है। यह संपत्ति के मूल्य को एक आदिम या एक ऑब्जेक्ट अप्रासंगिक है।

तो, जब आप करते हैं

 var parent = { x: {a:0} }; var child = Object.create(parent); 

child.x के समान वस्तु को parent.x – वह एक {a:0} ऑब्जेक्ट और जब आप इसे की संपत्ति बदलते हैं:

 var prop_val = child.x; // == parent.x prop_val.a = 1; 

दोनों प्रभावित होंगे स्वतंत्र रूप से "नेस्टेड" संपत्ति को बदलने के लिए, आपको पहले एक स्वतंत्र ऑब्जेक्ट बनाना होगा:

 child.x = {a:0}; child.xa = 1; parent.xa; // still 0 

आप क्या कर सकते हैं

 child.x = Object.create(parent.x); child.xa = 1; delete child.xa; // (child.x).a == 0, because child.x inherits from parent.x delete child.x; // (child).xa == 0, because child inherits from parent 

जिसका अर्थ है कि वे बिल्कुल स्वतंत्र नहीं हैं – लेकिन फिर भी दो अलग-अलग वस्तुओं।

मुझे लगता है कि क्या हो रहा है यह है कि जब आप 2 व्यक्ति बनाते हैं, तो उसके बारे में sex और info गुणों को उन लोगों को देखें जो nestObj जब आप person2.info संदर्भित person2.info , क्योंकि 2 person2 info संपत्ति को फिर से परिभाषित नहीं करता है, यह प्रोटोटाइप तक जाता है और उस वस्तु को संशोधित करता है।

ऐसा लगता है कि ऐसा करने का "सही" तरीका यह है कि जिस तरह से आप person3 , ताकि ऑब्जेक्ट को अपनी info वस्तु को संशोधित कर सके और प्रोटोटाइप तक नहीं जा सके।

मैं किताब (धीरे ​​धीरे) पढ़ रहा हूं, इसलिए मैं आपके साथ सहानुभूति करता हूं। 🙂

मैंने उदाहरणों को बदल दिया है कि आपको यहाँ क्या हो रहा है का बेहतर प्रदर्शन करने के लिए। डेमो

पहले हम तीन गुणों के साथ एक वस्तु बनाते हैं; संख्या, एक स्ट्रिंग और स्ट्रिंग मान वाले एक प्रॉपर्टी के साथ ऑब्जेक्ट।

फिर हम पहले ऑब्जेक्ट का उपयोग करके एक दूसरा ऑब्जेक्ट बनाते हैं Object.create() ;

 var obj1 = { num : 1, str : 'foo', obj : { less: 'more' } }; var obj2 = Object.create( obj1 ); console.log( '[1] obj1:', obj1 ); console.log( '[1] obj2:', obj2 ); 
 "[1] obj1:" [object Object] { num: 1, obj: [object Object] { less: "more" }, str: "foo" } "[1] obj2:" [object Object] { num: 1, obj: [object Object] { less: "more" }, str: "foo" } 

अच्छा लगता है? हमारे पास अपना पहला ऑब्जेक्ट और दूसरा कॉपी ऑब्जेक्ट है।

इतना शीघ्र नही; देखते हैं कि जब हम पहले ऑब्जेक्ट पर कुछ वैल्यू बदलते हैं तो क्या होता है।

 obj1.num = 3; obj1.str = 'bar'; obj1.obj.less = 'less'; console.log( '[2] obj1:', obj1 ); console.log( '[2] obj2:', obj2 ); 
 "[2] obj1:" [object Object] { num: 3, obj: [object Object] { less: "less" }, str: "bar" } "[2] obj2:" [object Object] { num: 3, obj: [object Object] { less: "less" }, str: "bar" } 

अब फिर से हमारा पहला ऑब्जेक्ट, परिवर्तनों के साथ, और उस ऑब्जेक्ट की प्रतिलिपि है। यहाँ क्या हो रहा है?

चलो देखते हैं कि ऑब्जेक्ट के पास अपनी संपत्ति है

 for( var prop in obj1 ) console.log( '[3] obj1.hasOwnProperty( ' + prop + ' ): ' + obj1.hasOwnProperty( prop ) ); for( var prop in obj2 ) console.log( '[3] obj2.hasOwnProperty( ' + prop + ' ): ' + obj2.hasOwnProperty( prop ) ); 
 "[3] obj1.hasOwnProperty( num ): true" "[3] obj1.hasOwnProperty( str ): true" "[3] obj1.hasOwnProperty( obj ): true" "[3] obj2.hasOwnProperty( num ): false" "[3] obj2.hasOwnProperty( str ): false" "[3] obj2.hasOwnProperty( obj ): false" 

obj1 के सभी गुण हैं, जैसे हम परिभाषित हैं, लेकिन obj2 नहीं है

जब हम कुछ obj2 के गुण बदलते हैं तो क्या होता है?

 obj2.num = 1; obj2.str = 'baz'; obj2.obj.less = 'more'; console.log( '[4] obj1:', obj1 ); console.log( '[4] obj2:', obj2 ); for( var prop in obj1 ) console.log( '[4] obj1.hasOwnProperty( ' + prop + ' ): ' + obj1.hasOwnProperty( prop ) ); for( var prop in obj2 ) console.log( '[4] obj2.hasOwnProperty( ' + prop + ' ): ' + obj2.hasOwnProperty( prop ) ); 
 "[4] obj1:" [object Object] { num: 3, obj: [object Object] { less: "more" }, str: "bar" } "[4] obj2:" [object Object] { num: 1, obj: [object Object] { less: "more" }, str: "baz" } "[4] obj1.hasOwnProperty( num ): true" "[4] obj1.hasOwnProperty( str ): true" "[4] obj1.hasOwnProperty( obj ): true" "[4] obj2.hasOwnProperty( num ): true" "[4] obj2.hasOwnProperty( str ): true" "[4] obj2.hasOwnProperty( obj ): false" 

इसलिए, num और str obj2 पर बदल दिया गया है और नहीं obj1 पर जैसे हम चाहते थे, लेकिन obj1.obj.less बदल गया जब इसे नहीं होना चाहिए।

hasOwnProperty() चेक से हम यह देख सकते हैं, भले ही हम obj2.obj.less बदल obj2.obj.less , हमने पहले obj2.obj सेट नहीं किया। इसका मतलब यह है कि हम अभी भी obj1.obj.less बात कर रहे हैं

आइए obj1.obj से ऑब्जेक्ट obj1.obj और इसे obj2.obj लिए आवंटित करते हैं और देखें कि क्या हमें यह बताता है कि हम क्या ढूंढ रहे हैं।

 obj2.obj = Object.create( obj1.obj ); console.log( '[5] obj1:', obj1 ); console.log( '[5] obj2:', obj2 ); for( var prop in obj1 ) console.log( '[5] obj1.hasOwnProperty( ' + prop + ' ): ' + obj1.hasOwnProperty( prop ) ); for( var prop in obj2 ) console.log( '[5] obj2.hasOwnProperty( ' + prop + ' ): ' + obj2.hasOwnProperty( prop ) ); 
 "[5] obj1:" [object Object] { num: 3, obj: [object Object] { less: "more" }, str: "bar" } "[5] obj2:" [object Object] { num: 1, obj: [object Object] { less: "more" }, str: "baz" } "[5] obj1.hasOwnProperty( num ): true" "[5] obj1.hasOwnProperty( str ): true" "[5] obj1.hasOwnProperty( obj ): true" "[5] obj2.hasOwnProperty( num ): true" "[5] obj2.hasOwnProperty( str ): true" "[5] obj2.hasOwnProperty( obj ): true" 

यह अच्छा है, अब obj2 की अपनी obj संपत्ति है देखते हैं कि जब हम obj2.obj.less बदलते हैं obj2.obj.less अब क्या होता है।

 obj2.obj.less = 'less'; console.log( '[6] obj1:', obj1 ); console.log( '[6] obj2:', obj2 ); 
 "[6] obj1:" [object Object] { num: 3, obj: [object Object] { less: "more" }, str: "bar" } "[6] obj2:" [object Object] { num: 1, obj: [object Object] { less: "less" }, str: "baz" } 

तो यह सब हमें बताता है कि, यदि संपत्ति बनाई गई वस्तु पर अभी तक नहीं बदली गई है, तो उस संपत्ति के लिए बनाई वस्तु को कोई भी अनुरोध get करना मूल वस्तु के लिए अग्रेषित किया जाएगा।

obj2.obj.less = 'more' लिए पिछले कोड ब्लॉक से सेट को पहले obj2.obj लिए एक अनुरोध get करने की आवश्यकता है, जो उस बिंदु पर obj2 में मौजूद नहीं है, इसलिए यह obj1.obj आगे और बदले में obj1.obj.less

आखिरकार जब हम obj2.obj पढ़ते हैं, तो हम अभी भी obj2.obj सेट नहीं obj2.obj ताकि अनुरोध get करने के लिए obj1.obj को भेजा जाएगा और उस सेटिंग को वापस कर दिया जाएगा जिसे हमने पहले बदल दिया था, जिसके परिणामस्वरूप दूसरा ऑब्जेक्ट ऑब्जेक्ट की संपत्ति बदल रही है बच्चे दोनों को बदलते हैं, लेकिन वास्तव में यह केवल वास्तव में पहली बार बदल रहा है


आप इस फ़ंक्शन का उपयोग मूल पुनरावर्ती मूल से पूरी तरह से अलग किए गए एक नए ऑब्जेक्ट को वापस करने के लिए कर सकते हैं।

डेमो

 var obj1 = { num : 1, str : 'foo', obj : { less: 'more' } }; var obj2 = separateObject( obj1 ); function separateObject( obj1 ) { var obj2 = Object.create( Object.getPrototypeOf( obj1 ) ); for(var prop in obj1) { if( typeof obj1[prop] === "object" ) obj2[prop] = separateObject( obj1[prop] ); else obj2[prop] = obj1[prop]; } return obj2; } console.log( '[1] obj1:', obj1 ); console.log( '[1] obj2:', obj2 ); for( var prop in obj1 ) console.log( '[1] obj1.hasOwnProperty( ' + prop + ' ): ' + obj1.hasOwnProperty( prop ) ); for( var prop in obj2 ) console.log( '[1] obj2.hasOwnProperty( ' + prop + ' ): ' + obj2.hasOwnProperty( prop ) ); 
 "[1] obj1:" [object Object] { num: 1, obj: [object Object] { less: "more" }, str: "foo" } "[1] obj2:" [object Object] { num: 1, obj: [object Object] { less: "more" }, str: "foo" } "[1] obj1.hasOwnProperty( num ): true" "[1] obj1.hasOwnProperty( str ): true" "[1] obj1.hasOwnProperty( obj ): true" "[1] obj2.hasOwnProperty( num ): true" "[1] obj2.hasOwnProperty( str ): true" "[1] obj2.hasOwnProperty( obj ): true" 

देखते हैं कि जब हम कुछ वैरिएबल्स बदलते हैं तो क्या होता है।

 obj1.num = 3; obj1.str = 'bar'; obj1.obj.less = 'less'; console.log( '[2] obj1:', obj1 ); console.log( '[2] obj2:', obj2 ); 
 "[2] obj1:" [object Object] { num: 3, obj: [object Object] { less: "less" }, str: "bar" } "[2] obj2:" [object Object] { num: 1, obj: [object Object] { less: "more" }, str: "foo" } 

सबकुछ ठीक उसी तरह से काम करता है जिसकी आप उम्मीद करते थे।