it-swarm.com.de

Wie rufe ich eine übergeordnete Methode aus der Kindklasse in Javascript auf?

Ich habe die letzten paar Stunden damit verbracht, eine Lösung für mein Problem zu finden, aber es scheint hoffnungslos zu sein.

Grundsätzlich muss ich wissen, wie eine übergeordnete Methode von einer untergeordneten Klasse aufgerufen wird .. __ All das, was ich bisher ausprobiert habe, führt dazu, dass die übergeordnete Methode entweder nicht funktioniert oder überschrieben wird.

Ich verwende den folgenden Code, um OOP in Javascript einzurichten:

// SET UP OOP
// surrogate constructor (empty function)
function surrogateCtor() {}

function extend(base, sub) {
    // copy the prototype from the base to setup inheritance
    surrogateCtor.prototype = base.prototype;
    sub.prototype = new surrogateCtor();
    sub.prototype.constructor = sub;
}

// parent class
function ParentObject(name) {
    this.name = name;
}
// parent's methods
ParentObject.prototype = {
    myMethod: function(arg) {
        this.name = arg;
    }
}

// child
function ChildObject(name) {
    // call the parent's constructor
    ParentObject.call(this, name);
    this.myMethod = function(arg) {
        // HOW DO I CALL THE PARENT METHOD HERE?
        // do stuff
    }
}

// setup the prototype chain
extend(ParentObject, ChildObject);

Ich muss zuerst die Elternmethode aufrufen und dann in der Kinderklasse etwas mehr hinzufügen.

In den meisten OOP - Sprachen wäre das so einfach wie das Aufrufen von parent.myMethod() Aber ich kann wirklich nicht verstehen, wie es in Javascript gemacht wird.

Jede Hilfe wird sehr geschätzt, danke! 

100
YemSalat

So wird's gemacht: ParentClass.prototype.myMethod();

Oder wenn Sie es im Kontext der aktuellen Instanz aufrufen möchten, können Sie Folgendes tun: ParentClass.prototype.myMethod.call(this)

Dasselbe gilt für das Aufrufen einer übergeordneten Methode aus untergeordneten Klassen mit Argumenten: ParentClass.prototype.myMethod.call(this, arg1, arg2, ..) * Hinweis: Verwenden Sie apply() anstelle von call(), um Argumente als Array zu übergeben.

147
YemSalat

Im ES6-Stil können Sie neue Funktionen verwenden, beispielsweise das Schlüsselwort super. Beim super-Schlüsselwort dreht sich alles um den übergeordneten Klassenkontext, wenn Sie die ES6-Klassensyntax verwenden. Als sehr einfaches Beispiel checkout:

class Foo {
    static classMethod() {
        return 'hello';
    }
}

class Bar extends Foo {
    static classMethod() {
        return super.classMethod() + ', too';
    }
}
Bar.classMethod(); // 'hello, too'

Sie können auch super verwenden, um den übergeordneten Konstruktor aufzurufen:

class Foo {}

class Bar extends Foo {
    constructor(num) {
        let tmp = num * 2; // OK
        this.num = num; // ReferenceError
        super();
        this.num = num; // OK
    }
}

Natürlich können Sie damit auch auf die Eigenschaften der übergeordneten Klasse super.prop..__ zugreifen. Verwenden Sie also ES6 und seien Sie glücklich.

83
Dmytro Medvid

Um dies zu tun, sind Sie nicht auf die Class-Abstraktion von ES6 beschränkt. Der Zugriff auf die Prototyp-Methoden des übergeordneten Konstruktors ist über die __proto__-Eigenschaft möglich (ich bin mir ziemlich sicher, dass es andere JS-Codierer geben wird, die sich beschweren, dass sie abgeschrieben wird) (vor allem für die Array-Unterklassierungsanforderungen). Während die __proto__-Eigenschaft noch in allen mir bekannten JS-Engines verfügbar ist, hat ES6 die Object.getPrototypeOf() - Funktionalität darüber hinaus eingeführt. Das super()-Tool in der Class-Abstraktion ist ein syntaktischer Zucker davon.

Falls Sie also keinen Zugriff auf den Namen des übergeordneten Konstruktors haben und die Class-Abstraktion nicht verwenden möchten, können Sie dennoch wie folgt vorgehen:

function ChildObject(name) {
    // call the parent's constructor
    ParentObject.call(this, name);
    this.myMethod = function(arg) {
    //this.__proto__.__proto__.myMethod.call(this,arg);
    Object.getPrototypeOf(Object.getPrototypeOf(this)).myMethod.call(this,arg);
    }
}
3
Redu

Bei Mehrfachvererbung kann diese Funktion in anderen Sprachen als Super () - Methode verwendet werden. Hier ist eine Demo-Geige , mit einigen Tests kannst du es so benutzen, innerhalb deiner Methode verwenden: call_base(this, 'method_name', arguments);

Es werden aktuelle ES-Funktionen verwendet, eine Kompatibilität mit älteren Browsern kann nicht garantiert werden. Getestet in IE11, FF29, CH35.

/**
 * Call super method of the given object and method.
 * This function create a temporary variable called "_call_base_reference",
 * to inspect whole inheritance linage. It will be deleted at the end of inspection.
 *
 * Usage : Inside your method use call_base(this, 'method_name', arguments);
 *
 * @param {object} object The owner object of the method and inheritance linage
 * @param {string} method The name of the super method to find.
 * @param {array} args The calls arguments, basically use the "arguments" special variable.
 * @returns {*} The data returned from the super method.
 */
function call_base(object, method, args) {
    // We get base object, first time it will be passed object,
    // but in case of multiple inheritance, it will be instance of parent objects.
    var base = object.hasOwnProperty('_call_base_reference') ? object._call_base_reference : object,
    // We get matching method, from current object,
    // this is a reference to define super method.
            object_current_method = base[method],
    // Temp object wo receive method definition.
            descriptor = null,
    // We define super function after founding current position.
            is_super = false,
    // Contain output data.
            output = null;
    while (base !== undefined) {
        // Get method info
        descriptor = Object.getOwnPropertyDescriptor(base, method);
        if (descriptor !== undefined) {
            // We search for current object method to define inherited part of chain.
            if (descriptor.value === object_current_method) {
                // Further loops will be considered as inherited function.
                is_super = true;
            }
            // We already have found current object method.
            else if (is_super === true) {
                // We need to pass original object to apply() as first argument,
                // this allow to keep original instance definition along all method
                // inheritance. But we also need to save reference to "base" who
                // contain parent class, it will be used into this function startup
                // to begin at the right chain position.
                object._call_base_reference = base;
                // Apply super method.
                output = descriptor.value.apply(object, args);
                // Property have been used into super function if another
                // call_base() is launched. Reference is not useful anymore.
                delete object._call_base_reference;
                // Job is done.
                return output;
            }
        }
        // Iterate to the next parent inherited.
        base = Object.getPrototypeOf(base);
    }
}
3
weeger

Wie wäre es mit etwas, das auf der Idee von Douglas Crockford basiert:

    function Shape(){}

    Shape.prototype.name = 'Shape';

    Shape.prototype.toString = function(){
        return this.constructor.parent
            ? this.constructor.parent.toString() + ',' + this.name
            : this.name;
    };


    function TwoDShape(){}

    var F = function(){};

    F.prototype = Shape.prototype;

    TwoDShape.prototype = new F();

    TwoDShape.prototype.constructor = TwoDShape;

    TwoDShape.parent = Shape.prototype;

    TwoDShape.prototype.name = '2D Shape';


    var my = new TwoDShape();

    console.log(my.toString()); ===> Shape,2D Shape
2
Alex

Hier ist eine nette Möglichkeit für untergeordnete Objekte, über die JavaScript-Prototypkette auf übergeordnete Eigenschaften und Methoden zuzugreifen, und sie ist mit Internet Explorer kompatibel. JavaScript durchsucht die Prototypkette nach Methoden und die Prototypkette des Kindes sieht folgendermaßen aus:

Child-Instanz -> Child-Prototyp (mit Child-Methoden) -> Parent-Prototyp (mit Parent-Methoden) -> Objektprototyp -> null

Die untergeordneten Methoden können auch gespiegelte übergeordnete Methoden aufrufen (siehe die drei Sternchen *** unten).

Hier ist wie:

//Parent constructor
function ParentConstructor(firstName){
    //add parent properties:
    this.parentProperty = firstName;
}

//add 2 Parent methods:
ParentConstructor.prototype.parentMethod = function(argument){
    console.log(
            "Parent says: argument=" + argument +
            ", parentProperty=" + this.parentProperty +
            ", childProperty=" + this.childProperty
    );
};

ParentConstructor.prototype.commonMethod = function(argument){
    console.log("Hello from Parent! argument=" + argument);
};

//Child constructor    
function ChildConstructor(firstName, lastName){
    //first add parent's properties
    ParentConstructor.call(this, firstName);

    //now add child's properties:
    this.childProperty = lastName;
}

//insert Parent's methods into Child's prototype chain
var rCopyParentProto = Object.create(ParentConstructor.prototype);
rCopyParentProto.constructor = ChildConstructor;
ChildConstructor.prototype = rCopyParentProto;

//add 2 Child methods:
ChildConstructor.prototype.childMethod = function(argument){
    console.log(
            "Child says: argument=" + argument +
            ", parentProperty=" + this.parentProperty +
            ", childProperty=" + this.childProperty
    );
};

ChildConstructor.prototype.commonMethod = function(argument){
    console.log("Hello from Child! argument=" + argument);

    // *** call Parent's version of common method
    ParentConstructor.prototype.commonMethod(argument);
};

//create an instance of Child
var child_1 = new ChildConstructor('Albert', 'Einstein');

//call Child method
child_1.childMethod('do child method');

//call Parent method
child_1.parentMethod('do parent method');

//call common method
child_1.commonMethod('do common method');

0
CaptureWiz

Es gibt eine viel einfachere und kompaktere Lösung für die Suche nach Prototypen mit mehreren Ebenen, jedoch ist die Unterstützung von Proxy erforderlich. Verwendung: SUPER(<instance>).<method>(<args>), beispielsweise unter der Annahme, dass zwei Klassen A und B extends A mit der Methode m: SUPER(new B).m() verwendet werden.

function SUPER(instance)
{
    return new Proxy(instance,
    {
        get(target, prop)
        {
            return Object.getPrototypeOf(Object.getPrototypeOf(target))[prop].bind(target);
        }
    });
}
0
ZzZombo