2013-03-19 33 views
5

पर बाद में परिवर्तन पर झूठा लौटाता है जब एक प्रोटोटाइप फ़ंक्शन पर प्रोटोटाइप सेट किया जाता है, तो instanceof ऑपरेटर केवल true लौटाता है जब तक कि प्रोटोटाइप बदल नहीं जाता है। क्यूं कर?उदाहरण ऑपरेटर विरासत श्रृंखला

function SomeConstructorFunction() { 
} 

function extendAndInstantiate(constructorFn) { 
    constructorFn.prototype = {}; //Can be any prototype 
    return new constructorFn(); 
} 

var child1 = extendAndInstantiate(SomeConstructorFunction); 
console.log(child1 instanceof SomeConstructorFunction); //true 

var child2 = extendAndInstantiate(SomeConstructorFunction); 
console.log(child1 instanceof SomeConstructorFunction); //false 
console.log(child2 instanceof SomeConstructorFunction); //true 

उत्तर

3

प्रोटोटाइप विरासत एक मस्तिष्क बेंडर का थोड़ा सा हो सकता है। मैंने पहले से ही निम्नलिखित उत्तर में प्रोटोटाइप विरासत के लिए एक सरल स्पष्टीकरण लिखा है और मेरा सुझाव है कि आप इसे पढ़ लें: https://stackoverflow.com/a/8096017/783743

अब आपके प्रश्न का उत्तर देने के लिए।निम्नलिखित समारोह पर विचार करें:

function F() {} 

इस प्रकार मैं new का उपयोग कर F का एक उदाहरण बना सकते हैं: f instanceof F रिटर्न true उम्मीद

var f = new F; 

के रूप में। ऐसा इसलिए है क्योंकि instanceof ऑपरेटर f की प्रोटोटाइप श्रृंखला में F.prototype के लिए जांच करता है और यदि वहां है तो true लौटाता है। ऊपर दिए गए उत्तर को देखें।

function G() {} 

F.prototype = G.prototype; 

अब मैं मूल्यांकन f instanceof F फिर false लौटाया जाता है:

अब इस प्रकार मैं एक नया समारोह G बना सकते हैं और G.prototype करने के लिए F.prototype सेट कहते हैं। ऐसा इसलिए है क्योंकि F.prototype अब f की प्रोटोटाइप श्रृंखला में नहीं है (याद रखें कि F.prototype अब G.prototype है)।

अब F का एक नया उदाहरण बना सकते हैं:

var g = new F; 

आप g instanceof G का मूल्यांकन अगर यह true भी g = new F हालांकि आरंभ कर देंगे। ऐसा इसलिए है क्योंकि G.prototypeg की प्रोटोटाइप श्रृंखला में मौजूद है।

यह एक बग नहीं है। जावास्क्रिप्ट काम करता है। असल में हम कुछ वाकई दिलचस्प कार्यों को बनाने के लिए इस सुविधा का फायदा उठा सकते हैं: Instantiate JavaScript functions with custom prototypes

+0

प्रोटोटाइप विरासत का महान स्पष्टीकरण। मुझे लगता है कि ओपी का भ्रम 'constructorFn.prototype = {} में निहित है; // कोई प्रोटोटाइप हो सकता है। वह उम्मीद कर रहा है कि प्रोटोटाइप को उसी ** मान ** पर सेट करने के परिणामस्वरूप 'exampleof' सत्य होगा, इसके बजाए, उन्हें उसी ** संदर्भ ** पर सेट किया जाना चाहिए। – MattDiamant

+0

@MattDiamant - मैं सहमत हूं। मुझे नहीं पता कि ओपी 'विस्तार और इंस्टेंटिएट' का उपयोग करके पूरा करने का प्रयास कर रहा है, लेकिन मेरा मानना ​​है कि यह निम्नलिखित प्रश्न में मेरे अपने 'तत्काल' समारोह की तरह थोड़ा सा है: http://stackoverflow.com/q/11490606/783743 –

+0

अच्छी व्याख्या । सबसे महत्वपूर्ण बात यह है कि, मैं इस तथ्य को याद कर रहा था कि '{}' प्रोटोटाइप को 'ऑब्जेक्ट' में प्रभावी रूप से 'कुछ कॉन्स्ट्रक्टर फंक्शन' के प्रकार को बदलता है। 'कुछ कन्स्ट्रक्टर फंक्शनक्शन। कन्स्ट्रक्टर' 'कार्य ऑब्जेक्ट ...' है। – Stephen

3
constructorFn.prototype = {}; //Can be any prototype 

सही नहीं है!

constructorFn.prototype = Object.prototype; 

या कोई अन्य मूल प्रोटोटाइप उन्हें सब सच कर देगा।

कारण यह है कि पहली बार जब आप extendAndInstantiate() पर कॉल कर रहे हैं, तो आप कुछ कॉन्स्ट्रास्ट्रक्टर फ़ंक्शन का प्रोटोटाइप कुछ (यहां एक खाली ऑब्जेक्ट {}) सेट कर रहे हैं। child1 के लिए, instanceOf केवल तब ही सही होगा जब कुछ कॉन्स्ट्रक्टर फंक्शन का प्रोटोटाइप {} का सटीक उदाहरण है। जब आप extendAnInstantiate() दूसरी बार चलाने के लिए, आप {} का एक अलग उदाहरण के लिए SomeConstructorFunction के प्रोटोटाइप बदल रहे हैं, तो child2 एक instanceof कि नए {} होगा, लेकिन child1 अभी भी पुराने {} के instanceof है, इसलिए child1 अवास्तविक लौटाते हैं, जबकि child2 सच लौट रहा है। यदि आप प्रोटोटाइप को एक सामान्य प्रोटोटाइप पर सेट करते हैं, जैसे कि Object.prototype या Array.prototype, यह हमेशा सत्य वापस आ जाएगा।

इसे चित्रित करने का एक और तरीका है {} फ़ंक्शन से बाहर खींचें, और उसे एक चर obj पर असाइन करें।

var obj = {}; 
function extendAndInstantiate(constructorFn) { 
    constructorFn.prototype = obj; 
    return new constructorFn(); 
} 

अब इस हमेशा सच वापस आ जाएगी, क्योंकि आप एक नया {} हर बार जब आप समारोह चलाने रचना नहीं करते हैं।

0

instanceof प्रोटोटाइप ऑब्जेक्ट पर आधारित है।

function extendAndInstantiate(constructorFn) { 
constructorFn.prototype = {}; //Can be any prototype 
... 

जब आप प्रोटोटाइप को {} पर सेट करते हैं तो आप एक नई वस्तु बना रहे हैं और इसे प्रोटोटाइप के रूप में सेट कर रहे हैं। क्योंकि यह प्रोटोटाइप के समान वस्तु नहीं है, instanceof झूठी रिटर्न देता है।

इस तरह का सेटअप सभी मामलों के लिए सही वापस आ जाएगी, क्योंकि प्रोटोटाइप का उद्देश्य एक ही हो जाएगा:

function SomeConstructorFunction() { 
} 

var emptyObj = {}; 

function extendAndInstantiate(constructorFn) { 
    constructorFn.prototype = emptyObj; 
    return new constructorFn(); 
} 

var child1 = extendAndInstantiate(SomeConstructorFunction); 
console.log(child1 instanceof SomeConstructorFunction); //true 

var child2 = extendAndInstantiate(SomeConstructorFunction); 
console.log(child1 instanceof SomeConstructorFunction); //true 
console.log(child2 instanceof SomeConstructorFunction); //true 
0

हर बार जब आप extendAndInstantiate एक नई वस्तु {} का उपयोग कर बनाई गई है फोन और यह प्रोटोटाइप के रूप में असाइन किया गया है SomeConstructorFunction का। यह मौजूदा उदाहरणों और SomeConstructorFunction के बीच लिंक को साफ़ करता है। तो केवल अंतिम एक SomeConstructorFunction का मान्य उदाहरण होगा।

function SomeConstructorFunction() { 

} 

function extendAndInstantiate(constructorFn) { 
    constructorFn.prototype = {}; //New instance as prototype 
    return new constructorFn(); 
} 

var child1 = extendAndInstantiate(SomeConstructorFunction); 
console.log(child1 instanceof SomeConstructorFunction); //true 

var child2 = extendAndInstantiate(SomeConstructorFunction); 
console.log(child1 instanceof SomeConstructorFunction); //false 
console.log(child2 instanceof SomeConstructorFunction); //true 


var child3 = extendAndInstantiate(SomeConstructorFunction); 
console.log(child1 instanceof SomeConstructorFunction); //false 
console.log(child2 instanceof SomeConstructorFunction); //false 
console.log(child3 instanceof SomeConstructorFunction); //true 

तो या तो आप नीचे दिखाए गए प्रोटोटाइप को निर्दिष्ट करने से पहले @ ben336 द्वारा दिखाए गए तरीके का पालन कर सकते हैं या एक शर्त जांच कर सकते हैं।

function Base(){ 

} 

function SomeConstructorFunction() { 

} 

function extendAndInstantiate(constructorFn, Base) { 
    if(!(constructorFn.prototype instanceof Base)){ 
    console.log(" extend only once "); 
    constructorFn.prototype = new Base(); 
    } 
    return new constructorFn(); 
} 


var child1 = extendAndInstantiate(SomeConstructorFunction, Base); 
console.log(child1 instanceof SomeConstructorFunction); //true 

var child2 = extendAndInstantiate(SomeConstructorFunction, Base); 
console.log(child1 instanceof SomeConstructorFunction); //true 
console.log(child2 instanceof SomeConstructorFunction); //true 


var child3 = extendAndInstantiate(SomeConstructorFunction, Base); 
console.log(child1 instanceof SomeConstructorFunction); //true 
console.log(child2 instanceof SomeConstructorFunction); //true 
console.log(child3 instanceof SomeConstructorFunction); //true 
संबंधित मुद्दे