2012-06-17 9 views
5

मेरे पास एक निर्माता समारोह है, जो एक सुपर क्लास के रूप में कार्य:वस्तुओं नमूने के कार्यों के वारिस नहीं है

Bla = function(a){this.a = a;} 

मैं यह एक सरल विधि शामिल करने के लिए प्रोटोटाइप:

Bla.prototype.f = function(){console.log("f"); 

और अब नए Bla(1).f(); होगा कंसोल में लॉग "एफ" लॉग इन करें। लेकिन, की सुविधा देता है का कहना है कि मैं एक उपवर्ग कि Bla से विरासत की जरूरत है:

Bla2 = function(a) 
{ 
    this.base = Bla; 
    this.base(); 
} 

x = new Bla2(5); 

अब, के रूप में उम्मीद, x.a मुझे 5 देता है। लेकिन, x.fundefined है! ऐसा लगता है कि Bla2Bla कक्षा से इसका उत्तराधिकारी नहीं था! यह क्यों हो रहा है और मैं इसे कैसे ठीक करूं?

+2

यह क्योंकि अपने कोड में कुछ भी नहीं है इसके लिए * * ऐसा नहीं व्यवस्था हो रहा है।। यदि आप सोच रहे हैं कि "आधार" नामक एक संपत्ति को सेट करने से एक वर्ग दूसरे से प्राप्त होता है, तो यह गलत है। – Pointy

+1

प्रारूपण के लिए धन्यवाद, @ मार्किनस! – corazza

+1

'Bla2.prototype' को 'नया Bla()' पर सेट करने का प्रयास करें। – Pointy

उत्तर

28

Bla2 जैसा लगता है Bla कक्षा से इसका उत्तराधिकारी नहीं था!

दाएं। आपने वहां विरासत को हुक करने के लिए कुछ भी नहीं किया है, आपने अभी Bla2 का सदस्य बनाया है जिसे base कहा जाता है जो Bla उदाहरण है। base जावास्क्रिप्ट में एक विशेष पहचानकर्ता नहीं है।

जावास्क्रिप्ट में विरासत स्थापित करने के लिए विशिष्ट तरीका इस तरह दिखता है:

// The base constructor function 
function Base(x) { 
    // Base per-instance init 
    this.x = x; 
} 

// An example Base function 
Base.prototype.foo = function() { 
    console.log("I'm Base#foo, x = " + this.x); 
}; 

// The Derived constructor function 
function Derived(x, y) { 
    // Normally you need to call `Base` as it may have per-instance 
    // initialization it needs to do. You need to do it such that 
    // within the call, `this` refers to the current `this`, so you 
    // use `Function#call` or `Function#apply` as appropriate. 
    Base.call(this, x); 

    // Derived per-instance init 
    this.y = y; 
} 

// Make the Derived.prototype be a new object backed up by the 
// Base.prototype.  
Derived.prototype = Object.create(Base.prototype); 

// Fix up the 'constructor' property 
Derived.prototype.constructor = Derived; 

// Add any Derived functions 
Derived.prototype.bar = function() { 
    console.log("I'm Derived#bar, x = " + this.x + ", y = " + this.y); 
}; 

... जहां Object.create ES5 से है, लेकिन यह चीजें हैं जो आसानी से ज्यादातर shimmed किया जा सकता है में से एक है। (या फिर आप एक समारोह है कि केवल Object.create सब करने की कोशिश कर के बिना न्यूनतम करता है का उपयोग कर सकते, नीचे देखें।) और फिर आप इसका इस्तेमाल करते हैं:

var d = new Derived(4, 2); 
d.foo(); // "I'm Base#foo, x = 4" 
d.bar(); // "I'm Derived#bar, x = 4, y = 2" 

Live example | source

पुराने कोड में आप कभी कभी देखने Derived.prototype इस तरह के बजाय सेट अप:

Derived.prototype = new Base(); 

... लेकिन इसे उस तरह से कर रही है के साथ एक समस्या है: Base जो नहीं है प्रति-उदाहरण प्रारंभ कर सकते हैं उत्तराधिकारी के लिए Derived की संपूर्णता के लिए उपयुक्त है। इसे तर्कों की भी आवश्यकता हो सकती है (क्योंकि हमारे Base करता है; हम x के लिए क्या पास करेंगे?)। Derived.prototype बनाने के बजाय Base.prototype द्वारा समर्थित एक नई ऑब्जेक्ट बनें, हमें सही चीज़ें मिलती हैं। फिर हम प्रति उदाहरण इन्सिट प्राप्त करने के लिए Derived के भीतर Base पर कॉल करते हैं।

उपरोक्त बहुत बुनियादी है और जैसा कि आप देख सकते हैं कि कई कदम शामिल हैं। यह "supercalls" को आसान और अत्यधिक रखरखाव करने के लिए बहुत कम या कुछ भी नहीं करता है। यही कारण है कि आप प्रोटोटाइप के Class, डीन एडवर्ड्स 'बेस 2, या (खांसी) जैसे अपने स्वयं के Lineage जैसे कई "विरासत" स्क्रिप्ट देखते हैं।


आप अपने वातावरण में ES5 सुविधाओं होने पर भरोसा नहीं कर सकते हैं, और एक परत है कि Object.create की मूल बातें करता है शामिल करने के लिए नहीं करना चाहते हैं, तो आप सिर्फ उसके स्थान पर इस सुविधा का उपयोग कर सकते हैं:

function simpleCreate(proto) { 
    function Ctor() { 
    } 
    ctor.prototype = proto; 
    return new Ctor(); 
} 

तो बजाय

Derived.prototype = Object.create(Base.prototype); 

तुम क्या चाहते हैं:

Derived.prototype = simpleCreate(Base.prototype); 

बेशक, आप   — पर हुकिंग चीजों को स्वचालित करने के लिए और अधिक कर सकते हैं जो सभी Lineage मूल रूप से करता है।


... और अंत में: ऊपर मैं सादगी के लिए अनाम प्रक्रियाएं का उपयोग किया है, उदा .:

Base.prototype.foo = function() { 
    // ... 
}; 

... लेकिन मैं ऐसा नहीं करते हैं मेरा असली कोड में, क्योंकि वह I like to help my tools help me। इसलिए मैं प्रत्येक "वर्ग" (कन्स्ट्रक्टर फ़ंक्शन और संबंधित प्रोटोटाइप) के आसपास मॉड्यूल पैटर्न का उपयोग करता हूं और फ़ंक्शन घोषणा (क्योंकि मैं वेब के लिए काम करता हूं, और आईई 7 और आईई 8 still have problems नामित फ़ंक्शन एक्सप्रेशन के साथ उपयोग करता हूं। इसलिए यदि मैं ' Lineage का उपयोग कर टी, मैं ऊपर इस तरह करना चाहते हैं:

// Base 
(function(target) { 
    // Base constructor 
    target.Base = Base; 
    function Base(x) { 
     // Base per-instance init 
     this.x = x; 
    } 

    // An example Base function 
    Base.prototype.foo = Base$foo; 
    function Base$foo() { 
     console.log("I'm Base#foo, x = " + this.x); 
    } 
})(window); 

// Derived 
(function(target, base) { 
    // The Derived constructor function 
    target.Derived = Derived; 
    function Derived(x, y) { 
     // Init base 
     base.call(this, x); 

     // Derived per-instance init 
     this.y = y; 
    } 

    // Make the Derived.prototype be a new object backed up by the 
    // Base.prototype.  
    Derived.prototype = Object.create(base.prototype); 

    // Fix up the 'constructor' property 
    Derived.prototype.constructor = Derived; 

    // Add any Derived functions 
    Derived.prototype.bar = Derived$bar; 
    function Derived$bar() { 
     console.log("I'm Derived#bar, x = " + this.x + ", y = " + this.y); 
    } 
})(window, Base); 

... या ऐसा ही कुछ Live copy | source

+6

अच्छी तरह से संरचित, बहुत ही जानकारीपूर्ण उत्तर। +1 – Kaii

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