जावास्क्रिप्ट वंशानुक्रम [बंद]


80

मैं जावास्क्रिप्ट में विरासत को लागू करने की कोशिश कर रहा हूं। मैं इसका समर्थन करने के लिए न्यूनतम कोड का पालन कर रहा हूं।

function Base(){
    this.call = function(handler, args){
      handler.call(this, args);
    }
}

Base.extend = function(child, parent){
    parent.apply(child);
    child.base = new parent;
    child.base.child = child;
}

विशेषज्ञ, कृपया मुझे बताएं कि क्या यह पर्याप्त होगा या कोई अन्य महत्वपूर्ण मुद्दा जो मुझे याद होगा। सामना किए गए समान मुद्दों के आधार पर कृपया अन्य परिवर्तन सुझाएं।

यहाँ पूरी परीक्षण स्क्रिप्ट है:

function Base(){
    this.call = function(handler, args){
      handler.call(this, args);
    }
    this.superalert = function(){
        alert('tst');
    }
}

Base.extend = function(child, parent){
    parent.apply(child);
    child.base = new parent;
    child.base.child = child;
}

function Child(){
    Base.extend(this, Base);
    this.width = 20;
    this.height = 15;
    this.a = ['s',''];
    this.alert = function(){
        alert(this.a.length);
        alert(this.height);
    }
}

function Child1(){
    Base.extend(this, Child);
    this.depth = 'depth';
    this.height = 'h';
    this.alert = function(){
        alert(this.height); // display current object height
        alert(this.a.length); // display parents array length
        this.call(this.base.alert); 
          // explicit call to parent alert with current objects value
        this.call(this.base.superalert); 
          // explicit call to grandparent, parent does not have method 
        this.base.alert(); // call parent without overriding values
    }
}

var v = new Child1();
v.alert();
alert(v.height);
alert(v.depth);

यदि आपको विरासत की आवश्यकता है तो कई, कई पुस्तकालय पहले से ही यह पेशकश कर रहे हैं। बहुत कम से कम उन्हें यह पता लगाने के लिए पढ़ें कि आप कहां कोड गलत है। लेकिन पुनर्निमाण क्यों? दो भयानक जावास्क्रिप्ट विरासत पुस्तकालय जो मन में आते हैं वे काजल और स्वार्थी हैं।
जेएस

मैंने क्लास का उपयोग किया है लेकिन सरणी चर को ओवरराइड करने में कुछ समस्या है। मैं स्वार्थी कोशिश करूंगा। लेकिन मेरा संस्करण सरल 4 लाइन कोड है, लेकिन अधिकांश परिदृश्य में मेरे लिए काम करता है। मैं सिर्फ यह जानना चाहता हूं कि क्या मैं इस दृष्टिकोण के साथ बाद में फंस जाऊंगा।
भूखा मिन्द

2
आप इसी तरह के प्रश्न के लिए इस एसओ उत्तर की समीक्षा करना चाहते हैं ; सभी महान सुझावों के बीच लेखक दिखाता है कि बच्चे के वर्ग को परिभाषित करते समय माता-पिता के निर्माता को कॉल कैसे हटाएं।
बेजोनबी

@hungryMind: यदि आप अपने कोड के बारे में विशेष समस्याओं से चिंतित हैं, तो आप अपने प्रश्न को संपादित क्यों नहीं करते और हमें बताएं कि आप किससे डरते हैं। क्योंकि जब से आप बस पूछ रहे हैं कि क्या आपका कोड ठीक है, तो यह बहुत न्याय नहीं देता है। आपको शायद वे उत्तर नहीं मिलेंगे जिनकी आप तलाश कर रहे हैं। इसलिए मेरा सुझाव है कि आप अपने Q.
रॉबर्ट कोरिटनिक को 20'11

यह प्रश्न उसी विषय के बारे में है: stackoverflow.com/questions/711209/…
एंडरसन ग्रीन

जवाबों:


139

ECMAScript 5 में जावास्क्रिप्ट वंशानुक्रम को लागू करने के लिए आप किसी ऑब्जेक्ट के प्रोटोटाइप को परिभाषित कर सकते हैं और Object.createइनहेरिट करने के लिए उपयोग कर सकते हैं। आप अपनी इच्छानुसार गुणों को जोड़ सकते हैं / ओवरराइड कर सकते हैं।

उदाहरण:

/**
 * Transform base class
 */
function Transform() {
    this.type = "2d";
}

Transform.prototype.toString = function() {
    return "Transform";
}

/**
 * Translation class.
 */
function Translation(x, y) {
    // Parent constructor
    Transform.call(this);

    // Public properties
    this.x = x;
    this.y = y;
}

// Inheritance
Translation.prototype = Object.create(Transform.prototype);

// Override
Translation.prototype.toString = function() {
    return Transform.prototype.toString() + this.type + " Translation " + this.x + ":" + this.y;
}

/**
 * Rotation class.
 */
function Rotation(angle) {
    // Parent constructor
    Transform.call(this);

    // Public properties
    this.angle = angle;
}

// Inheritance
Rotation.prototype = Object.create(Transform.prototype);

// Override
Rotation.prototype.toString = function() {
    return Transform.prototype.toString() + this.type + " Rotation " + this.angle;
}

// Tests
translation = new Translation(10, 15);

console.log(translation instanceof Transform); // true
console.log(translation instanceof Translation); // true
console.log(translation instanceof Rotation); // false

console.log(translation.toString()) // Transform2d Translation 10:15

2
अनुवाद.प्रकरण = Object.create (नया ट्रांसफ़ॉर्म ()); ? ट्रांसलेशन.प्रोटोटाइप = ऑब्जेक्ट.क्रिएट (ट्रांसफॉर्मप्रोटाइप);
4esn0k

@ 4esn0k यह सही है, धन्यवाद।
लोरेंजो पोलिडोरी

सिर्फ क्यों नहीं Translation.prototype = new Transform()? इसके अलावा, चूंकि उत्तर वर्तमान में काम नहीं कर रहा है, क्या आप इसे संपादित करेंगे?
जोहान ज़ेफर

@ JörnZaefferer यहाँ एक नज़र है: stackoverflow.com/q/4166616/885464 । और the वर्तमान में काम नहीं कर रहा है ’का क्या मतलब है?
लोरेंजो पोलिडोरी

4
आप यह भी स्पष्ट रूप से उपवर्ग के निर्माता स्थापित करना चाहिए: Translation.prototype.constructor = Translation। ऑब्जेक्ट को क्लोन करने के लिए उपयोगी (अधिकांश तकनीकों में)।
बारबोज

41

मुझे लगता है कि जॉन के रूप में क्रॉकफॉर्ड्स समाधान बहुत जटिल है। उन दोनों की तुलना में जावास्क्रिप्ट उत्तराधिकार प्राप्त करना बहुत सरल है। विचार करें:

//Classes
function A() {
    B.call(this);
}

function B() {
    C.call(this);
    this.bbb = function() {
        console.log("i was inherited from b!");
    }
}

function C() {
    D.call(this);
}

function D() {
    E.call(this);
}

function E() {
    //instance property 
    this.id = Math.random()
}

//set up the inheritance chain (order matters) 
D.prototype = new E();
C.prototype = new D();
B.prototype = new C();
A.prototype = new B();

//Add custom functions to each
A.prototype.foo = function() {
    console.log("a");
};
B.prototype.bar = function() {
    console.log("b");
};
C.prototype.baz = function() {
    console.log("c");
};
D.prototype.wee = function() {
    console.log("d");
};
E.prototype.woo = function() {
    console.log("e");
};

//Some tests
a = new A();
a.foo();
a.bar();
a.baz();
a.wee();
a.woo();
console.log(a.id);
a.bbb();
console.log(a instanceof A);
console.log(a instanceof B);
console.log(a instanceof C);
console.log(a instanceof D);
console.log(a instanceof E);​
var b = new B();
console.log(b.id)

मैंने अपने ब्लॉग पर उपरोक्त समाधान का पूरा विवरण लिखा है ।


1
सिवाय इसके कि यह सभी सार्वजनिक सदस्यों का समर्थन करता है
रॉडरिगो-सिल्वेरा

@ रॉडरिगो-सिलवीरा, निश्चित नहीं कि आपका क्या मतलब है। यदि आप निजीकरण चाहते हैं, तो आप बस उन्हें var x = "जो भी" के साथ घोषित करें, नहीं?
मार्कोस

2
मुझे लगता है कि @ रॉडरिगो-सिलवीरा का मतलब था कि यह संरक्षित सदस्यों का समर्थन नहीं करता है, न ही समाधान करता है। (परिभाषा के अनुसार निजी सदस्य उपवर्ग से सुलभ नहीं हैं, इसलिए इसका कोई मतलब नहीं होगा)। आपको this._myProtectedVariable = 5;संरक्षित सदस्यों को बनाने के लिए कुछ का उपयोग करना होगा ।
Ciantic

10
बहुत अच्छा समाधान, केवल (मामूली) दोष, कंस्ट्रक्टरों को दो बार निष्पादित किया जाता है। एक बार D.call (यह), और फिर से: नया D ()। यह आमतौर पर कोई बड़ी समस्या नहीं है, लेकिन अगर आप इसे टालना चाहते हैं, तो आप इस तरह से Object.create का उपयोग कर सकते हैं: इसके बजाय C.prototype = new D (); आप C.prototype = Object.create (D.prototype) लिख सकते हैं; उदाहरण: jsfiddle.net/9Dxkb/1
रे हुलहा

1
अंत में, एक गैर-समझा स्पष्टीकरण जो काम करता है! मैंने ई तर्क को उल्टी दिशा में बनाने के लिए आपके तर्क को उलट दिया (ई के पास सबसे अधिक है) जो मेरे लिए समझ में आता है। धन्यवाद!
एड बेयेट्स

12

जैसा कि मैंने JS ऑब्जेक्ट्स के साथ खेला था, मुझे एक और न्यूनतर समाधान मिला :-) आनंद लें!

function extend(b,a,t,p) { b.prototype = a; a.apply(t,p); }

उदाहरण

function A() {
    this.info1 = function() {
        alert("A");
    }
}

function B(p1,p2) {
    extend(B,A,this);
    this.info2 = function() {
        alert("B"+p1+p2);
    }
}

function C(p) {
    extend(C,B,this,["1","2"]);
    this.info3 = function() {
        alert("C"+p);
    }
}


var c = new C("c");
c.info1(); // A
c.info2(); // B12
c.info3(); // Cc

8

यहां सबसे सरल है और मुझे उम्मीद है कि जेएस में विरासत को समझने का सबसे आसान तरीका है। सबसे अधिक सहायक यह उदाहरण PHP प्रोग्रामर के लिए होगा।

function Mother(){
    this.canSwim = function(){
        console.log('yes');
    }
}

function Son(){};
Son.prototype = new Mother;
Son.prototype.canRun = function(){
    console.log('yes');
}

अब बेटे के पास एक ओवरराइड विधि और एक नया है

function Grandson(){}
Grandson.prototype = new Son;
Grandson.prototype.canPlayPiano = function(){
    console.log('yes');
};
Grandson.prototype.canSwim = function(){
    console.log('no');
}

अब पोते के पास दो वर्जित तरीके हैं और एक नया

var g = new Grandson;
g.canRun(); // => yes
g.canPlayPiano(); // => yes
g.canSwim(); // => no


यकीन है कि यह Object.create (नए बेटे) के रूप में लागू करना संभव है
अलेक्जेंडर सेर्किन

यह और भी बुरा होगा।
बरगी

4

कार्यों के बजाय वस्तुओं का उपयोग क्यों नहीं करें:

var Base = {
    superalert : function() {
        alert('tst');
    }
};

var Child = Object.create(Base);
Child.width = 20;
Child.height = 15;
Child.a = ['s',''];
Child.childAlert = function () {
        alert(this.a.length);
        alert(this.height);
    }

var Child1 = Object.create(Child);
Child1.depth = 'depth';
Child1.height = 'h';
Child1.alert = function () {
    alert(this.height);
    alert(this.a.length);
    this.childAlert();
    this.superalert();
};

और इसे इस तरह से कॉल करें:

var child1 = Object.create(Child1);
child1.alert();

यह दृष्टिकोण बहुत अधिक क्लीनर है फिर कार्यों के साथ। मैंने इस ब्लॉग को यह समझाते हुए पाया कि जेएस में कार्यों के साथ वंशानुक्रम इसे करने का उचित तरीका क्यों नहीं है: http://davidwalsh.name/javascript-objects-deconstruction

संपादित करें

var बाल को भी लिखा जा सकता है:

var Child = Object.create(Base, {
    width : {value : 20},
    height  : {value : 15, writable: true},
    a : {value : ['s', ''], writable: true},
    childAlert : {value : function () {
        alert(this.a.length);
        alert(this.height);
    }}
});

4

यहां मेरा समाधान है, जो कि लोरेंजो पोलिडोरी के उत्तर में वर्णित मानक प्रोटोटाइप विरासत विधि पर आधारित है ।

सबसे पहले, मैं इन सहायक तरीकों को परिभाषित करके शुरू करता हूं, जो बाद में चीजों को समझने में आसान और अधिक पठनीय हैं:

Function.prototype.setSuperclass = function(target) {
    // Set a custom field for keeping track of the object's 'superclass'.
    this._superclass = target;

    // Set the internal [[Prototype]] of instances of this object to a new object
    // which inherits from the superclass's prototype.
    this.prototype = Object.create(this._superclass.prototype);

    // Correct the constructor attribute of this class's prototype
    this.prototype.constructor = this;
};

Function.prototype.getSuperclass = function(target) {
    // Easy way of finding out what a class inherits from
    return this._superclass;
};

Function.prototype.callSuper = function(target, methodName, args) {
    // If methodName is ommitted, call the constructor.
    if (arguments.length < 3) {
        return this.callSuperConstructor(arguments[0], arguments[1]);
    }

    // `args` is an empty array by default.
    if (args === undefined || args === null) args = [];

    var superclass = this.getSuperclass();
    if (superclass === undefined) throw new TypeError("A superclass for " + this + " could not be found.");

    var method = superclass.prototype[methodName];
    if (typeof method != "function") throw new TypeError("TypeError: Object " + superclass.prototype + " has no method '" + methodName + "'");

    return method.apply(target, args);
};

Function.prototype.callSuperConstructor = function(target, args) {
    if (args === undefined || args === null) args = [];

    var superclass = this.getSuperclass();
    if (superclass === undefined) throw new TypeError("A superclass for " + this + " could not be found.");

    return superclass.apply(target, args);
};

अब, आप न केवल एक वर्ग के सुपरक्लास के साथ सेट कर सकते हैं SubClass.setSuperclass(ParentClass), बल्कि आप इसके साथ ओवरराइड तरीके भी कह सकते हैं SubClass.callSuper(this, 'functionName', [argument1, argument2...]):

/**
 * Transform base class
 */
function Transform() {
    this.type = "2d";
}

Transform.prototype.toString = function() {
    return "Transform";
}

/**
 * Translation class.
 */
function Translation(x, y) {
    // Parent constructor
    Translation.callSuper(this, arguments);

    // Public properties
    this.x = x;
    this.y = y;
}
// Inheritance
Translation.setSuperclass(Transform);

// Override
Translation.prototype.toString = function() {
    return Translation.callSuper(this, 'toString', arguments) + this.type + " Translation " + this.x + ":" + this.y;
}

/**
 * Rotation class.
 */
function Rotation(angle) {
    // Parent constructor
    Rotation.callSuper(this, arguments);

    // Public properties
    this.angle = angle;
}
// Inheritance
Rotation.setSuperclass(Transform);

// Override
Rotation.prototype.toString = function() {
    return Rotation.callSuper(this, 'toString', arguments) + this.type + " Rotation " + this.angle;
}

// Tests
translation = new Translation(10, 15);

console.log(translation instanceof Transform); // true
console.log(translation instanceof Translation); // true
console.log(translation instanceof Rotation); // false

console.log(translation.toString()) // Transform2d Translation 10:15

जाहिर है, सहायक कार्यों के साथ भी यहाँ वाक्य रचना बहुत अजीब है। शुक्र है कि हालांकि, ECMAScript 6 में चीजों को ज्यादा प्रिटियर करने के लिए कुछ सिंथैटिक शुगर ( अधिकतम न्यूनतम कक्षाएं ) जोड़ी गई हैं। उदाहरण के लिए:

/**
 * Transform base class
 */
class Transform {
  constructor() {
    this.type = "2d";
  }

  toString() {
    return "Transform";
  } 
}

/**
 * Translation class.
 */
class Translation extends Transform {
  constructor(x, y) {
    super(); // Parent constructor

    // Public properties
    this.x = x;
    this.y = y;
  }

  toString() {
    return super(...arguments) + this.type + " Translation " + this.x + ":" + this.y;
  }
}

/**
 * Rotation class.
 */
class Rotation extends Transform {
  constructor(angle) {
    // Parent constructor
    super(...arguments);

    // Public properties
    this.angle = angle;
  }

  toString() {
    return super(...arguments) + this.type + " Rotation " + this.angle;
  }
}

// Tests
translation = new Translation(10, 15);

console.log(translation instanceof Transform); // true
console.log(translation instanceof Translation); // true
console.log(translation instanceof Rotation); // false

console.log(translation.toString()) // Transform2d Translation 10:15

ध्यान दें कि ECMAScript 6 इस बिंदु पर अभी भी मसौदा चरण में है, और जहाँ तक मुझे पता है कि किसी भी प्रमुख वेब ब्राउज़र में लागू नहीं किया गया है। हालाँकि, यदि आप चाहें तो सादे पुराने- आधारित जावास्क्रिप्ट को संकलित करने के लिए ट्रेसर कंपाइलर जैसी किसी चीज़ का उपयोग कर सकते हैं । आप यहां ट्रेसेर का उपयोग करके संकलित उपरोक्त उदाहरण देख सकते हैं ।ECMAScript 6ECMAScript 5


2

जबकि मैं उपरोक्त सभी उत्तरों से सहमत हूं, मुझे लगता है कि जावास्क्रिप्ट को ऑब्जेक्ट ओरिएंटेड नहीं होना चाहिए, (इनहेरिटेंस से बचें), इसके बजाय ऑब्जेक्ट-आधारित दृष्टिकोण अधिकांश मामलों में पर्याप्त होना चाहिए।

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


2
//This is an example of how to override a method, while preserving access to the original.
//The pattern used is actually quite simple using JavaScripts ability to define closures:

    this.somefunction = this.someFunction.override(function(args){
        var result = this.inherited(args);
        result += this.doSomethingElse();
        return result;
    });

//It is accomplished through this piece of code (courtesy of Poul Krogh):

/***************************************************************
    function.override overrides a defined method with a new one, 
    while preserving the old method.
    The old method is only accessible from the new one.
    Use this.inherited() to access the old method.
***************************************************************/

    Function.prototype.override = function(func)
    {
        var remember = this;
        var f = function() 
        {
             var save = this.inherited; 
             this.inherited = remember;
             var result = func.apply(this, Array.prototype.slice.call(arguments));
             this.inherited = save;
             return result;
        };
        return f;
    }

1

इस सरल दृष्टिकोण के बारे में कैसे

    function Body(){
        this.Eyes = 2;
        this.Arms = 2;
        this.Legs = 2;
        this.Heart = 1;
        this.Walk = function(){alert(this.FirstName + ' Is Walking')};
    }

    function BasePerson() {
        var BaseBody = new Body(this);
        BaseBody.FirstName = '';
        BaseBody.LastName = '';
        BaseBody.Email = '';
        BaseBody.IntroduceSelf = function () { alert('Hello my name is ' + this.FirstName + ' ' + this.LastName); };
        return BaseBody;
    }

    function Person(FirstName,LastName)
    {
        var PersonBuild = new BasePerson();
        PersonBuild.FirstName = FirstName;
        PersonBuild.LastName = LastName;
        return PersonBuild;
    }

    var Person1 = new Person('Code', 'Master');
    Person1.IntroduceSelf();
    Person1.Walk();

1

बुनियादी प्रोटोटाइप विरासत

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

B.prototype = Object.create(A.prototype);
B.prototype.constructor = B;

यह करने के समान है:

B.prototype = new A();

दोनों के बीच मुख्य अंतर यह है कि निर्माणकर्ता का Aउपयोग करते समय नहीं चलाया जाता हैObject.create , जो कि अधिक सहज और वर्ग आधारित विरासत के समान है।

आप कंस्ट्रक्टर को वैकल्पिक रूप से चलाने के लिए हमेशा चुन सकते हैं Aजब इसे बनाने वाले के साथ Bजोड़कर एक नया उदाहरण बनाया जाए B:

function B(arg1, arg2) {
    A(arg1, arg2); // This is optional
}

आप सभी तर्कों पास करना चाहते हैं Bके लिए A, आप भी उपयोग कर सकते हैं Function.prototype.apply():

function B() {
    A.apply(this, arguments); // This is optional
}

यदि आप किसी अन्य ऑब्जेक्ट को कंस्ट्रक्टर की श्रृंखला में मिलाना चाहते हैं B, तो आप इसके Object.createसाथ संयोजन कर सकते हैं Object.assign:

B.prototype = Object.assign(Object.create(A.prototype), mixin.prototype);
B.prototype.constructor = B;

डेमो

function A(name) {
  this.name = name;
}

A.prototype = Object.create(Object.prototype);
A.prototype.constructor = A;

function B() {
  A.apply(this, arguments);
  this.street = "Downing Street 10";
}

B.prototype = Object.create(A.prototype);
B.prototype.constructor = B;

function mixin() {

}

mixin.prototype = Object.create(Object.prototype);
mixin.prototype.constructor = mixin;

mixin.prototype.getProperties = function() {
  return {
    name: this.name,
    address: this.street,
    year: this.year
  };
};

function C() {
  B.apply(this, arguments);
  this.year = "2018"
}

C.prototype = Object.assign(Object.create(B.prototype), mixin.prototype);
C.prototype.constructor = C;

var instance = new C("Frank");
console.log(instance);
console.log(instance.getProperties());


अपना खुद का रैपर बनाना

यदि आपको अपने कोड में लगभग दो-लाइनर लिखना पसंद नहीं है, तो आप इस तरह से एक बेसिक रैपर फ़ंक्शन लिख सकते हैं:

function inheritance() {
  var args = Array.prototype.slice.call(arguments);
  var firstArg = args.shift();
  switch (args.length) {
  case 0:
    firstArg.prototype = Object.create(Object.prototype);
    firstArg.prototype.constructor = firstArg;
    break;
  case 1:
    firstArg.prototype = Object.create(args[0].prototype);
    firstArg.prototype.constructor = firstArg;
    break;
  default:
    for(var i = 0; i < args.length; i++) {
      args[i] = args[i].prototype;
    }
    args[0] = Object.create(args[0]);
    var secondArg = args.shift();
    firstArg.prototype = Object.assign.apply(Object, args);
    firstArg.prototype.constructor = firstArg;
  }
}

यह आवरण कैसे काम करता है:

  1. यदि आप एक पैरामीटर पास करते हैं, तो यह प्रोटोटाइप से वारिस होगा Object
  2. यदि आप दो पैरामीटर पास करते हैं, तो पहला प्रोटोटाइप दूसरे से विरासत में मिलेगा।
  3. यदि आप दो से अधिक पैरामीटर पास करते हैं, तो पहले का प्रोटोटाइप दूसरे से विरासत में मिलेगा और अन्य मापदंडों के प्रोटोटाइप में मिलाया जाएगा।

डेमो

function inheritance() {
  var args = Array.prototype.slice.call(arguments);
  var firstArg = args.shift();
  switch (args.length) {
  case 0:
    firstArg.prototype = Object.create(Object.prototype);
    firstArg.prototype.constructor = firstArg;
    break;
  case 1:
    firstArg.prototype = Object.create(args[0].prototype);
    firstArg.prototype.constructor = firstArg;
    break;
  default:
    for(var i = 0; i < args.length; i++) {
      args[i] = args[i].prototype;
    }
    args[0] = Object.create(args[0]);
    var secondArg = args.shift();
    firstArg.prototype = Object.assign.apply(Object, args);
    firstArg.prototype.constructor = firstArg;
  }
}

function A(name) {
  this.name = name;
}

inheritance(A);

function B() {
  A.apply(this, arguments);
  this.street = "Downing Street 10";
}

inheritance(B, A);

function mixin() {

}

inheritance(mixin);

mixin.prototype.getProperties = function() {
  return {
    name: this.name,
    address: this.street,
    year: this.year
  };
};

function C() {
  B.apply(this, arguments);
  this.year = "2018"
}

inheritance(C, B, mixin);

var instance = new C("Frank");
console.log(instance);
console.log(instance.getProperties());


ध्यान दें

Object.createIE9 + सहित प्रत्येक आधुनिक ब्राउज़र में सुरक्षित रूप से उपयोग किया जा सकता है। Object.assignIE के किसी भी संस्करण में काम नहीं करता है और न ही कुछ मोबाइल ब्राउज़र। इसे पॉलीफिल Object.create और / या करने की सिफारिश की जाती हैObject.assign यदि आप उनका उपयोग करना चाहते हैं और उन ब्राउज़रों का समर्थन करना चाहते हैं जो उन्हें लागू नहीं करते हैं।

आप के लिए एक polyfill पा सकते हैं Object.create यहाँ और के लिए एक Object.assign यहाँ


0
//
//  try this one:
//  
//    function ParentConstructor() {}
//    function ChildConstructor()  {}
//
//    var 
//        SubClass = ChildConstructor.xtendz( ParentConstructor );
//
Function.prototype.xtendz = function ( SuperCtorFn ) {

    return ( function( Super, _slice ) {

                // 'freeze' host fn 
                var
                    baseFn = this, 
                    SubClassCtorFn;

                // define child ctor
                SubClassCtorFn = function ( /* child_ctor_parameters..., parent_ctor_parameters[] */ ) {

                    // execute parent ctor fn on host object
                    // pass it last ( array ) argument as parameters
                    Super.apply( this, _slice.call( arguments, -1 )[0] );

                    // execute child ctor fn on host object
                    // pass remaining arguments as parameters
                    baseFn.apply( this, _slice.call( arguments, 0, -1 ) );

                };

                // establish proper prototype inheritance
                // 'inherit' methods
                SubClassCtorFn.prototype = new Super;

                // (re)establish child ctor ( instead of Super ctor )
                SubClassCtorFn.prototype.constructor = SubClassCtorFn;

                // return built ctor
                return SubClassCtorFn;

    } ).call( this, SuperCtorFn, Array.prototype.slice );
};

// declare parent ctor
function Sup( x1, x2 ) {
    this.parent_property_1 = x1;
    this.parent_property_2 = x2;
}

// define some methods on parent
Sup.prototype.hello = function(){ 
   alert(' ~  h e l l o   t h e r e  ~ ');
};


// declare child ctor
function Sub( x1, x2 ) {
    this.child_property_1 = x1;
    this.child_property_2 = x2;
}

var
    SubClass = Sub.xtendz(Sup), // get 'child class' ctor
    obj;

// reserve last array argument for parent ctor
obj = new SubClass( 97, 98, [99, 100] ); 

obj.hello();

console.log( obj );
console.log('obj instanceof SubClass      -> ', obj instanceof SubClass      );
console.log('obj.constructor === SubClass -> ', obj.constructor === SubClass );
console.log('obj instanceof Sup           -> ', obj instanceof Sup           );
console.log('obj instanceof Object        -> ', obj instanceof Object        );

//
//  Object {parent_property_1: 99, parent_property_2: 100, child_property_1: 97, child_property_2: 98}
//  obj instanceof SubClass      -> true
//  obj.constructor === SubClass -> true
//  obj instanceof Sup           -> true
//  obj instanceof Object        -> true
//

-1

AWeb पुस्तकालय का उपयोग करने का सबसे आसान तरीका । आधिकारिक नमूना:

   /**
     * A-class
     */
   var ClassA = AWeb.class({
     public : {
        /**
          * A-class constructor
          */
        constructor : function() {
           /* Private variable */
           this.variable1 = "A";
           this.calls = 0;
        },

        /**
          * Function returns information about the object
          */
        getInfo : function() {
           this.incCalls();

           return "name=" + this.variable1 + ", calls=" + this.calls;
        }
     },
     private : {
        /**
          * Private function
          */
        incCalls : function() {
           this.calls++;
        }
     }
  });
  /**
    * B-class
    */
  var ClassB = AWeb.class({
     extends : ClassA,
     public : {
        /**
          * B-class constructor
          */
        constructor : function() {
           this.super();

           /* Private variable */
           this.variable1 = "B";
        },

        /**
          * Function returns extended information about the object
          */
        getLongInfo : function() {
           return this.incCalls !== undefined ? "incCalls exists" : "incCalls undefined";
        }
     }
  });
  /**
    * Main project function
    */
  function main() {
     var a = new ClassA(),
         b = new ClassB();

     alert(
        "a.getInfo " + (a.getInfo ? "exists" : "undefined") + "\n" +
        "a.getLongInfo " + (a.getLongInfo ? "exists" : "undefined") + "\n" +

        "b.getInfo " + (b.getInfo ? "exists" : "undefined") + "\n" +
        "b.getLongInfo " + (b.getLongInfo ? "exists" : "undefined") + "\n" +

        "b.getInfo()=" + b.getInfo() + "\n" +
        "b.getLongInfo()=" + b.getLongInfo()
     );
  }

-1

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

var A = function (p) {
    if (p == null) p = this;
    p.a1 = 0;
    this.a2 = 0;
    var a3 = 0;
};

var B = function (p) {
    if (p == null) p = this;
    p.b1 = new A(this);
    this.b2 = new A(this);
    var b3 = new A(this);
    this b4 = new A();
};

var a = new A ();
var b = new B ();

परिणाम:

a
    a1        0
    a2        0
b
    a1        0
    b1
        a2    0
    b2
        a2    0
    b4
        a1    0
        a2    0

व्यावहारिक उदाहरण:

var Point = function (p) {
    if (p == null) p = this;
    var x = 0;
    var y = 0;
    p.getPoint = function () { return [x,y]; };
    p.setPoint = function (_x,_y) { x = _x; y = _y; };
};

var Dimension = function (p) {
    if (p == null) p = this;
    var w = 0;
    var h = 0;
    p.getDimension = function() { return [w,h] };
    p.setDimension = function(_w,_h) { w = _w; h = _h };
};

var Rect = function (p) {
    if (p == null) p = this;
    var dimension = new Dimension(this);
    var location  = new Point(this);
};

var rect = new Rect ();
rect.setDimension({w:30,h:40});
rect.setPoint({x:50,y:50});
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.