web-dev-qa-db-de.com

JavaScript-Überschreibungsmethoden

Nehmen wir an, Sie haben den folgenden Code:

function A() {
    function modify(){
       x = 300;
       y = 400;
    }
    var c = new C();
}

function B() {
    function modify(){
       x = 3000;
       y = 4000;
    }
    var c = new C();
}


C = function () {
   var x = 10;
   var y = 20;

   function modify() {
      x = 30;
      y = 40;
   };

   modify();
   alert("The sum is: " + (x+y));
}

Nun stellt sich die Frage, ob es eine Möglichkeit gibt, in der ich die Methode modify von C mit den Methoden in A und B überschreiben kann. In Java würden Sie das Schlüsselwort super verwenden, aber wie kann dies in JavaScript erreicht werden?

67
Daniel Nastase

Edit: Es ist jetzt sechs Jahre her, dass die ursprüngliche Antwort geschrieben wurde und sich vieles geändert hat!

  • Wenn Sie eine neuere Version von JavaScript verwenden, möglicherweise mit einem Tool wie Babel kompiliert, können Sie echte Klassen verwenden
  • Wenn Sie die von Angular oder React bereitgestellten klassenähnlichen Komponentenkonstruktoren verwenden, sollten Sie in den Dokumenten nach diesem Framework suchen.
  • Wenn Sie ES5 verwenden und mit Prototypen "falsche" Klassen erstellen, ist die Antwort unten immer noch so richtig wie immer. 

Viel Glück!


Die JavaScript-Vererbung sieht ein wenig anders aus als Java. So sieht das native JavaScript-Objektsystem aus:

// Create a class
function Vehicle(color){
  this.color = color;
}

// Add an instance method
Vehicle.prototype.go = function(){
  return "Underway in " + this.color;
}

// Add a second class
function Car(color){
  this.color = color;
}

// And declare it is a subclass of the first
Car.prototype = new Vehicle();

// Override the instance method
Car.prototype.go = function(){
  return Vehicle.prototype.go.call(this) + " car"
}

// Create some instances and see the overridden behavior.
var v = new Vehicle("blue");
v.go() // "Underway in blue"

var c = new Car("red");
c.go() // "Underway in red car"

Leider ist dies ein wenig hässlich und enthält keine sehr schöne Möglichkeit, "super" zu sein: Sie müssen manuell angeben, welche übergeordnete Klassenmethode Sie aufrufen möchten. Infolgedessen gibt es eine Vielzahl von Tools, die das Erstellen von Klassen angenehmer machen. Schauen Sie sich Prototype.js, Backbone.js oder eine ähnliche Bibliothek an, die eine schönere Syntax für OOP in js enthält.

120
Adam

Da dies ein Top-Hit bei Google ist, möchte ich eine aktualisierte Antwort geben.

Die Verwendung von ES6-Klassen macht die Vererbung und das Überschreiben von Methoden wesentlich einfacher:

'use strict';

class A {
    speak() {
        console.log("I'm A");
    }
}

class B extends A {
    speak() {
        super.speak();

        console.log("I'm B");
    }
}

var a = new A();
a.speak();
// Output:
// I'm A

var b = new B();
b.speak();
// Output:
// I'm A
// I'm B

Das Schlüsselwort super bezieht sich auf die übergeordnete Klasse, wenn es in der erbenden Klasse verwendet wird. Außerdem sind alle Methoden in der übergeordneten Klasse an die Instanz des untergeordneten Objekts gebunden, sodass Sie nicht super.method.apply(this); schreiben müssen.

Zur Kompatibilität: Die ES6-Kompatibilitätstabelle zeigt nur die aktuellsten Versionen der wichtigsten Player (meistens). V8-Browser gibt es seit Januar dieses Jahres (Chrome und Opera), und Firefox, der die SpiderMonkey JS-Engine verwendet, wird im nächsten Monat mit seiner offiziellen Firefox 45-Version unterrichtet. Auf der mobilen Seite unterstützt Android diese Funktion immer noch nicht, während iOS 9, vor fünf Monaten veröffentlicht, teilweise unterstützt wird.

Glücklicherweise gibt es Babel , eine JS-Bibliothek zum Neukompilieren von Harmony-Code in ES5-Code. Klassen und viele andere coole Features in ES6 können Ihren Javascript-Code deutlich lesbarer und wartbarer machen.

28
Yotam Ofek

Einmal sollte die Emulation des klassischen OO vermieden werden und stattdessen prototypisch OO verwendet werden. Eine nette Utility-Bibliothek für prototypische OO ist traits .

Statt Methoden zu überschreiben und Vererbungsketten einzurichten (man sollte immer die Objektzusammensetzung der Objektvererbung vorziehen), sollten Sie wiederverwendbare Funktionen in Eigenschaften bündeln und Objekte damit erstellen.

Live-Beispiel

var modifyA = {
    modify: function() {
        this.x = 300;
        this.y = 400;
    }
};

var modifyB = {
    modify: function() {
        this.x = 3000;
        this.y = 4000;
    }
};

C = function(trait) {
    var o = Object.create(Object.prototype, Trait(trait));

    o.modify();
    console.log("sum : " + (o.x + o.y));

    return o;
}

//C(modifyA);
C(modifyB);
6
Raynos

modify () ist in Ihrem Beispiel eine private Funktion, auf die nur von Ihrer A-, B- oder C-Definition aus zugegriffen werden kann. Sie müssten es als deklarieren

this.modify = function(){}

C hat keinen Bezug zu seinen übergeordneten Elementen, es sei denn, Sie übergeben es an C. Wenn C so eingerichtet ist, dass es von A oder B erbt, erbt es seine öffentlichen Methoden (nicht seine privaten Funktionen, wie Sie es von modify () definiert haben). Sobald C Methoden von seinem übergeordneten Element erbt, können Sie die geerbten Methoden überschreiben.

3
Alex Heyd

die Methode modify(), die Sie zuletzt aufgerufen haben, wird im globalen Kontext aufgerufen .__ Wenn Sie modify() überschreiben möchten, müssen Sie zuerst A oder B erben. 

Vielleicht versuchst du das:

In diesem Fall erbt CA

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

function B() {
    this.modify = function() {
        alert("in B");
    }
}

C = function() {
    this.modify = function() {
        alert("in C");
    };

    C.prototype.modify(); // you can call this method where you need to call modify of the parent class
}

C.prototype = new A();
2
lovesh

Nicht, wenn Sie alle Variablen "public" machen, d. H. Sie entweder direkt oder über die Function-Eigenschaft zu Mitgliedern der prototype machen.

var C = function( ) {
    this.x = 10 , this.y = 20 ;
    this.modify = function( ) {
        this.x = 30 , this.y = 40 ;
        console.log("(!) C >> " + (this.x + this.y) ) ;
    } ;
} ;

var A = function( ) {
    this.modify = function( ) {
       this.x = 300 , this.y = 400 ;
       console.log("(!) A >> " + (this.x + this.y) ) ;
    } ;
} ;
    A.prototype = new C ;

var B = function( ) {
    this.modify = function( ) {
       this.x = 3000 , this.y = 4000 ;
       console.log("(!) B >> " + (this.x + this.y) ) ;
    } ;
} ;


new C( ).modify( ) ;
new A( ).modify( ) ;
new B( ).modify( ) ; 

Sie werden einige Änderungen feststellen. 

Am wichtigsten ist nun der Aufruf des angeblichen Konstruktors "Super-Klassen" in dieser Zeile:

<name>.prototype = new C ;

Sowohl A als auch B haben jetzt einzeln modifizierbare -Mitglieder x und y. Dies wäre nicht der Fall, wenn wir stattdessen ... = C geschrieben hätten.

Dann sind x, y und modify alle "public" -Mitglieder, so dass ihnen eine andere Function zugewiesen wird

 <name>.prototype.modify = function( ) { /* ... */ }

wird die ursprüngliche Function durch diesen Namen "überschreiben".

Schließlich kann der Aufruf von modify nicht in der Function-Deklaration erfolgen, da der implizite Aufruf der "Superklasse" dann erneut ausgeführt wird, wenn wir die "Superklasse" auf die prototype-Eigenschaft der vermeintlichen "Unterklassen" setzen ".

Aber gut, so würden Sie so etwas in JavaScript machen.

HTH,

FK

1
FK82

function A() {
    var c = new C();
	c.modify = function(){
		c.x = 123;
		c.y = 333;
	}
	c.sum();
}

function B() {
    var c = new C();
	c.modify = function(){
		c.x = 999;
		c.y = 333;
	}
	c.sum();
}


C = function () {
   this.x = 10;
   this.y = 20;

   this.modify = function() {
      this.x = 30;
      this.y = 40;
   };
   
   this.sum = function(){
	this.modify();
	console.log("The sum is: " + (this.x+this.y));
   }
}

A();
B();

0
nghien_net 89