2010-05-04 12 views
23

कोड का केवल 3 लाइनों हैं, और अभी तक मैं आ रही परेशानी पूरी तरह से इस लोभी:क्रॉकफोर्ड की ऑब्जेक्ट निर्माण तकनीक में क्या हो रहा है?

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

(Prototypal Inheritance से)

  1. Object.create() एक खाली समारोह F कहा जाता है बनाने के द्वारा बाहर शुरू होता है। मैं सोच रहा हूं कि एक समारोह एक प्रकार का वस्तु है। यह F ऑब्जेक्ट कहां संग्रहीत किया जा रहा है? वैश्विक रूप से मुझे लगता है।

  2. अगला oldObject, o के रूप में पारित, F फ़ंक्शन का प्रोटोटाइप बन गया। फ़ंक्शन (यानी, ऑब्जेक्ट) F अब हमारे oldObject से "विरासत" है, इस अर्थ में कि नाम समाधान इसके माध्यम से मार्ग जाएगा। अच्छा, लेकिन मुझे उत्सुकता है कि ऑब्जेक्ट के लिए डिफ़ॉल्ट प्रोटोटाइप क्या है, ऑब्जेक्ट? क्या यह फ़ंक्शन-ऑब्जेक्ट के लिए भी सच है?

  3. अंत में, F तत्काल है और लौटाया गया है, हमारे newObject बन रहा है। new ऑपरेशन यहां कड़ाई से जरूरी है? F पहले से ही हमें क्या प्रदान करता है, या फ़ंक्शन-ऑब्जेक्ट्स और गैर-फ़ंक्शन-ऑब्जेक्ट्स के बीच कोई महत्वपूर्ण अंतर नहीं है? स्पष्ट रूप से इस तकनीक का उपयोग कर एक कन्स्ट्रक्टर फ़ंक्शन होना संभव नहीं होगा।

क्या अगली बार Object.create() होता है कहा जाता है? क्या वैश्विक कार्य F अधिलेखित है? निश्चित रूप से इसका पुन: उपयोग नहीं किया जाता है, क्योंकि इससे पहले कॉन्फ़िगर किए गए ऑब्जेक्ट्स को बदल दिया जाएगा। और क्या होता है यदि एकाधिक धागे Object.create() पर कॉल करते हैं, क्या F पर दौड़ की स्थिति को रोकने के लिए सिंक्रनाइज़ेशन का कोई भी प्रकार है?

उत्तर

29

1) Object.create() एक खाली समारोह एफ कहा जाता है मैं सोच रहा हूँ एक समारोह एक प्रकार वस्तु के है कि बनाने के द्वारा बाहर शुरू होता है। यह एफ ऑब्जेक्ट कहां संग्रहीत किया जा रहा है? वैश्विक रूप से मुझे लगता है।

नहीं, यह Object.create समारोह के स्थानीय गुंजाइश पर संग्रह किया गया है, हर बार जब आप आह्वान Object.create इस समारोह F बनाई जाएँगी।

तुम भी, एक और अधिक स्मृति कुशल कार्यान्वयन बना सकते हैं एक बंद पर F भंडारण के द्वारा, और पुन: उपयोग यह:

if (typeof Object.create !== "function") { 
    Object.create = (function() { 
    function F() {} // created only once 
    return function (o) { 
     F.prototype = o; // reused on each invocation 
     return new F(); 
    }; 
    })(); 
} 

2) हमारे oldObject इसके बाद, के रूप में ओ में पारित कर दिया, प्रोटोटाइप बन जाता है फंक्शनफंक्शन (यानी ऑब्जेक्ट) एफ में हमारे पुराने ऑब्जेक्ट से "विरासत" है, यह समझने के लिए कि नाम संकल्प इसके माध्यम से रूट करेगा। अच्छा, लेकिन मुझे उत्सुकता है कि डिफ़ॉल्ट प्रोटोटाइप ऑब्जेक्ट, ऑब्जेक्ट के लिए है? क्या यह फ़ंक्शन-ऑब्जेक्ट के लिए भी सच है?

सभी वस्तुओं यह एक आंतरिक संपत्ति है, हालांकि कुछ कार्यान्वयन आप इसे तक पहुँच, मोज़िला की तरह, obj.__proto__ संपत्ति के साथ जाने इस संपत्ति [[Prototype]] के रूप में जाना जाता है, एक आंतरिक संपत्ति है कि प्रोटोटाइप श्रृंखला बनाता है।

डिफ़ॉल्ट [[Prototype]] जब आप कोई नई ऑब्जेक्ट बनाते हैं, यानी var obj = {};Object.prototype है।

सभी कार्यों में prototype संपत्ति है, इस संपत्ति का उपयोग Constructor के रूप में किया जाता है, जिसे new ऑपरेटर के साथ बुलाया जाता है।

दृश्यों के पीछे यह एक नया ऑब्जेक्ट उदाहरण बनाया गया है, और यह ऑब्जेक्ट [[Prototype]] इसके कन्स्ट्रक्टर की prototype संपत्ति पर सेट है।

3) अंत में, एफ तत्काल है और लौटा, हमारा नया ऑब्जेक्ट बन गया। "नया" ऑपरेशन कड़ाई से आवश्यक है? क्या एफ पहले से ही प्रदान नहीं करता है, या क्या हमें फ़ंक्शन-ऑब्जेक्ट्स और गैर-फ़ंक्शन-ऑब्जेक्ट्स के बीच कोई महत्वपूर्ण अंतर है? स्पष्ट रूप से इस तकनीक का उपयोग कर कन्स्ट्रक्टर फ़ंक्शन होना संभव नहीं होगा।

हां, इस विधि में new ऑपरेटर आवश्यक है। यदि आप यह कैसे काम करता के बारे में उत्सुक हैं

new ऑपरेटर, एक वस्तु का [[Prototype]] आंतरिक गुण सेट करने के लिए केवल मानक तरीका है, आप [[Construct]] आंतरिक संचालन के लिए एक नज़र दे सकते हैं।

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

अगली बार Object.create शुरू हो जाती है, एक नया स्थानीय F समारोह केवल विधि कॉल के दायरे के भीतर instantiated है, तो आप के बारे में दौड़ की स्थिति चिंता नहीं करनी चाहिए।

ध्यान दें कि यह कार्यान्वयन ECMAScript 5th Edition Specification में वर्णित Object.create को उस विधि में वर्णित करता है, आप ऑब्जेक्ट को प्रारंभ करने के लिए एक संपत्ति डिस्क्रिप्टर पास कर सकते हैं।

सभी ब्राउज़र विक्रेता इसे कार्यान्वित कर रहे हैं (पहले से ही फ़ायरफ़ॉक्स 3.7 अल्फा, नवीनतम वीकिट नाइटली बिल्ड और क्रोम 5 बीटा पर उपलब्ध), इसलिए मैं आपको कम से कम यह जांचने की सलाह दूंगा कि मूल कार्यान्वयन इसे ओवरराइड करने से पहले मौजूद है या नहीं।

+0

हम्म, स्थानीय क्षेत्र के कारण क्रॉकफ़ोर्ड के लिए कोई दौड़ की स्थिति नहीं है, लेकिन आपके पुन: उपयोग संस्करण के बारे में क्या है? –

+0

@ क्रिस, कोई दौड़ की स्थिति भी नहीं, जावास्क्रिप्ट की प्रकृति एकल थ्रेडेड है, यहां तक ​​कि [टाइमर और अन्य असीमित घटनाएं] (http://ejohn.org/blog/how-javascript-timers-work/) जैसे उपयोगकर्ता इंटरैक्शन निष्पादित किया जाता है अनुक्रमिक रूप से एक अवरुद्ध एकल धागे में। – CMS

+0

उत्कृष्ट बिंदु-दर-बिंदु के लिए धन्यवाद! –

2

आपकी बड़ी गलतफहमी यह है कि एफ का वैश्विक दायरा है। यह ऑब्जेक्ट.क्रेट के शरीर में घोषित किया गया है और इसके परिणामस्वरूप केवल उस विधि ब्लॉक के दायरे में है।

+2

और, सी ++ लोगों की विस्मय करने के लिए, यह ब्लॉक निकास पर नष्ट नहीं कर रहा है । (संकेत, बनाई गई वस्तु एक संदर्भ रखती है, इसलिए जीसी इसे सीधे नहीं सुलझाता है, भले ही यह सीधे पहुंच योग्य न हो) – Javier

7

1) एक फ़ंक्शन वास्तव में एक प्रकार का ऑब्जेक्ट है। पहचानकर्ता F के साथ एक फ़ंक्शन ऑब्जेक्ट प्रत्येक बार Object.create कहा जाता है, और Object.create के निष्पादन के भीतर उस पहचानकर्ता के साथ ही पहुंच योग्य है। इसलिए, प्रत्येक बार Object.create कहा जाता है, आपको एक अलग फ़ंक्शन ऑब्जेक्ट F मिलता है। यह फ़ंक्शन ऑब्जेक्ट constructorObject.create द्वारा लौटाई गई वस्तु की संपत्ति के रूप में रहता है।

2)

एफ अब हमारे oldObject, से "Inherits" इस अर्थ में कि नाम संकल्प होगा मार्ग के माध्यम से यह

यह वास्तव में सही नहीं है। पर किसी ऑब्जेक्ट को prototype फ़ंक्शन की संपत्ति का असाइन करने का मतलब है कि इस फ़ंक्शन को कन्स्ट्रक्टर के रूप में कॉल करके बनाई गई भविष्य की ऑब्जेक्ट का प्रोटोटाइप someObject होगा।

3) new इस तकनीक के लिए बिल्कुल महत्वपूर्ण है। केवल एक कन्स्ट्रक्टर के रूप में फ़ंक्शन को कॉल करके यह एक नई वस्तु उत्पन्न करता है, और उस ऑब्जेक्ट का प्रोटोटाइप (जो आम तौर पर सुलभ नहीं होता है) कन्स्ट्रक्टर फ़ंक्शन की prototype संपत्ति पर सेट होता है। ऑब्जेक्ट के प्रोटोटाइप को सेट करने के लिए कोई अन्य (मानकीकृत) तरीका नहीं है।

अंत में, ब्राउज़र में जावास्क्रिप्ट एकल थ्रेडेड है, इसलिए आपके द्वारा वर्णित दौड़ की स्थिति संभव नहीं है।

+3

रेस की स्थिति वैसे भी लागू नहीं होगी, क्योंकि 'एफ'' ऑब्जेक्ट.क्रेट 'फ़ंक्शन के लिए स्थानीय है, न कि वैश्विक। –

+0

मैथ्यू: बहुत सच, धन्यवाद। –

2

> स्पष्ट रूप से इस तकनीक का उपयोग करके एक कन्स्ट्रक्टर फ़ंक्शन होना संभव नहीं होगा।

तकनीक पहले से ही एक ऑब्जेक्ट कन्स्ट्रक्टर है क्योंकि यह नया एफ() लौटाती है, लेकिन नए व्यक्ति ('जॉन', 'स्मिथ') के लिए कोई संपत्ति मूल्य निर्धारित नहीं किया जा सकता है। हालांकि, यदि ऑब्जेक्ट.क्रेट कोड संशोधित किया गया है, तो तत्कालता संभव है। उदाहरण के लिए नीचे साराह वस्तु का निर्माण किया जा सकता है और Object.creator का उपयोग करके तत्काल किया जा सकता है, और getName विधि का उत्तराधिकारी होगा।

var girl = { 
    name: '', 
    traits: {}, 
    getName: function(){return this.name} 
} 

var sarah = Object.creator(girl, 'Sarah', {age:29,weight:90}) 

सारा वस्तु तो खुद गुण शामिल होंगे {नाम: 'सारा', लक्षण: {उम्र: 9, वजन: 49}}, और प्रोटोटाइप sarah.getName() विरासत में मिला उत्पादन करेगा 'सारा' ।

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

Object.creator = function(o) { 
    var makeArgs = arguments 
    function F() { 
     var prop, i=1, arg, val 
     for(prop in o) { 
     if(!o.hasOwnProperty(prop)) continue 
     val = o[prop] 
     arg = makeArgs[i++] 
     if(typeof arg === 'undefined') break 
     this[prop] = arg 
     } 
    } 
    F.prototype = o 
    return new F() 
} 

आधिकारिक ECMA Object.create एक वैकल्पिक 2 पैरामीटर, propertiesObject, कि संपत्ति मूल्यों का दृष्टांत सकता है, लेकिन यह एक वस्तु के बजाय सामान्य सूची है, और उपयोग करने के लिए अजीब लग रहा है। जैसे मेरा मानना ​​है कि: -

o2 = Object.create({}, { p: { value: 42, writable: true, enumerable: true, configurable: true } }); 

बहुत सरल पुराने तरीके के बराबर है: -

o2 = new function(p) { this.p=p }(42) 

और

o2 = Object.creator({p:''}, 42) 
संबंधित मुद्दे