2011-10-21 12 views
5

मुझे इस कोड चलाएँ:जावास्क्रिप्ट विरासत जादू

function foo() { 
    console.log("foo"); 
    var self = this; 
    this.a = function() { 
     return arguments.length == 0 ? self.b : (self.b = arguments[0]); 
    }; 
}; 
function bar() { 
}; 
bar.prototype = new foo(); 
var a = new bar(); 
var b = new bar(); 
console.log(a.a()); 
b.a(true); 
console.log(a.a()); 

मैं निम्नलिखित उत्पादन प्राप्त करें: foo, undefined, true

क्या मुझे समझ नहीं आता कैसे वस्तु निर्माता समारोह foo द्वारा लौटाए गए किसी तरह एक आवंटित करने के लिए प्रबंधन करता है b के लिए नई मेमोरी लोकेशन। मैं पूरी तरह से अंतिम आउटपुट true होने की उम्मीद कर रहा था क्योंकि मुझे केवल 1 foo आउटपुट मिलता है।

यह काम बहुत अच्छा है, लेकिन यह जादू की तरह बहुत अधिक लगता है।

मेरी समस्या वास्तव में यहां है कि मैं प्रारंभिक क्रम (या श्रृंखला) सेट करना चाहता हूं। मुझे जो एहसास हुआ है वह है कि foo कोई तर्क नहीं ले सकता है, क्योंकि इसे बेस (या प्रकार के टेम्पलेट) प्रदान करने के लिए केवल एक बार कहा जाता है।

मैं एक बहुत आसान स्कीमा वसीयत के लिए जहां foo मानकों (क्योंकि bar विरासत foo) bar से foo के लिए पारित किया जाना है कि है चाहते हैं। bar से foo.apply(this, arguments) पर कॉल करने जैसे कुछ ठीक है, लेकिन प्रोटोटाइप सेट करने के लिए कॉल बिना तर्क के किया जाना है, मुझे किसी भी तरह से दो अलग-अलग बताए जाने का एक स्पष्ट तरीका है।

लेकिन मैं वास्तव में वस्तुओं है कि विरासत के कुछ प्रकार, केवल एक चीज मैं वास्तव में के बारे में, वस्तुओं निर्माण कर रही है सही ढंग से देखभाल के लिए अनुमति देते हैं बनाने के चारों ओर एक पूरे सेवा के निर्माण के लिए नहीं चाहता ...

+1

मुझे लॉग इन 'foo, undefined, true' मिलता है। अंतिम 'अपरिभाषित' क्रोम डेवलपर टूल्स में दिखाई देता है लेकिन यह सिर्फ 'console.log' का वापसी मान है। वैसे भी आपके पास केवल 3 लॉग हैं। – pimvdb

+0

हाँ, यह सही है, मैंने बस क्रोम कंसोल से आउटपुट से कॉपी किया है, याद किया कि ... –

+0

सवाल क्या है? – user123444555621

उत्तर

3

एक तरफ नोट पर, आप कभी-कभी self का उपयोग कर रहे हैं और कभी-कभी this का उपयोग कर रहे हैं ... व्यक्तिगत रूप से, मैं अधिक संगत होगा। मुझे that का उपयोग करना पसंद है क्योंकि this can be confusing और self is part of the BOM, लेकिन यह सिर्फ स्वाद का विषय है।

parasitic inheritance का प्रयास करें:

function foo(arg) { 
    var that = this; 
    that.a = function() { 
     return arguments.length == 0 ? that.b : (that.b = arguments[0]); 
    }; 
} 

function bar(arg) { 
    return new foo(arg); 
} 

bar.prototype = new foo(); 
var a = new bar(); // the `new` is now optional. Personally I'd remove it... 
var b = bar(); // ... like I did here! 
console.log(a.a()); 
b.a(true); 
console.log(a.a()); 
console.log(b.a()); 

... यहाँ विरासत एक अधिक प्रतिष्ठित में व्यवहार करती है, स्पष्ट रूप से एक माता पिता के निर्माता लागू जब निर्माता कहा जाता है।

+2

मुझे "उस" से नफरत है, यह इस से कुछ अलग बताता है। मैं "उदाहरण" –

+0

@ जॉर्ज जॉर्जी - पर्याप्त मेला पसंद करते हैं। मुझे लगता है कि महत्वपूर्ण हिस्सा सुसंगत होना है; उदाहरण के लिए 'this' और फिर 'self' का उपयोग न करें। –

+0

मैं स्थिरता के बारे में सहमत हूं। और मुझे पता है कि क्रॉकफोर्ड "उस" का उपयोग करता है, इसलिए मैं एक अंग पर थोड़ा सा हूं। –

0

खैर, यह है जेएस के कमजोर धब्बे (और फिर भी, मजबूत धब्बे) में से एक। आप यहां एक पैटर्न मुद्दे में भाग रहे हैं। मैं सुझाव देता हूं कि http://ejohn.org/blog/simple-javascript-inheritance/ पर एक नज़र डालें - एक निःशुल्क 'कक्षा' है जिसका उपयोग आप अधिक 'शास्त्रीय' विरासत के साथ अपेक्षा करने के लिए सीधे करने में सहायता के लिए कर सकते हैं।

बस एक त्वरित उदाहरण के रूप में, मैंने देखा है कि अधिकांश पैटर्न एक आधार 'वस्तु' (जो एक या अधिक अनुकूलित वर्ग है) और कन्स्ट्रक्टर (जो ऑब्जेक्ट कैसे बनाया जाता है 'कम या कम होता है) कॉल कुछ "this.init.apply (यह, तर्क)" जैसे कुछ। यह ऑब्जेक्ट पर 'इनिट' विधि को पारित किए गए सभी तर्कों के साथ कॉल करता है। तो इनिट को तब सेट किया जा सकता है, विस्तारित, फिर से सेट किया जा सकता है, आदि, और कन्स्ट्रक्टर हमेशा उस व्यक्ति को कॉल करता है जो पारित तर्कों के साथ स्वयं को 'स्थानीय' कहता है। काफी साफ़।

आशा है कि मदद करता है, या कम से कम भ्रमित नहीं करता है।

0

अंतिम आउटपुट true है। आपको अपने जावास्क्रिप्ट कंसोल द्वारा धोखा दिया जा रहा है। वह अंतिम undefined आपकी अभिव्यक्ति से वापसी मूल्य है।अपने console.log() कॉल अधिक क्या हो रहा है पर प्रकाश डालने के लिए वर्णनात्मक बनाएं:

function foo() { 
    console.log("foo constructor called"); 
    var self = this; 
    this.a = function() { 
     return arguments.length == 0 ? self.b : (self.b = arguments[0]); 
    }; 
} 
function bar() { 
} 
bar.prototype = new foo(); 
var a = new bar(); 
var b = new bar(); 
console.log("value from a.a(): " + a.a()); 
b.a(true); 
console.log("value from a.a(): " + a.a()); 
console.log("done logging"); 

इस कंसोल में निम्न उत्पादन पैदावार:

foo constructor called 
value from a.a(): undefined 
value from a.a(): true 
done logging 
undefined 
0

यह जादू नहीं है, यह मूलरूप विरासत है। मुझे लगता है कि आप जो हासिल करने की कोशिश कर रहे हैं वह स्वचालित रूप से कॉल करने के लिए दो कन्स्ट्रक्टर कार्यों का संयोजन कर रहा है। आप शायद रचनाकारों और प्रोटोटाइप को मिश्रित कर रहे हैं।

लेकिन मैं वास्तव में चारों ओर वस्तुओं है कि विरासत के कुछ प्रकार, केवल एक चीज मैं वास्तव में देखभाल के बारे में अनुमति देने के बनाने एक पूरी सेवा का निर्माण नहीं करना चाहती वस्तुओं निर्माण कर रही है, सही ढंग से ...

मुझे नहीं पता कि "सेवा" से आपका क्या मतलब है। लेकिन जैसा कि किसी अन्य ऑब्जेक्ट उन्मुख प्रोग्रामिंग भाषा में है, सुपरक्लास विधि कॉल मैन्युअल रूप से करने की आवश्यकता है। तो या तो आप कड़ी मेहनत से कोड इस तरह "सुपर-क्लास":

function foo() { 
    console.log("foo"); 
    var self = this; 
    this.a = function() { 
     return arguments.length == 0 ? self.b : (self.b = arguments[0]); 
    }; 
} 
function bar() { 
    foo.apply(this, arguments); // <- ugly 
} 
//bar.prototype = new foo(); // this is not neccessary 

... या आप किसी आवरण सामान का निर्माण अपने "वर्ग" कनेक्ट करने के लिए। कुछ ऐसा:

function inherit(superconstructor) { 
    return function() { 
     superconstructor.apply(this, arguments); 
    }; 
} 
function foo() {...} 
bar = inherit(foo); 
संबंधित मुद्दे