2016-03-28 11 views
0

Jetzt, da JavaScript Klassen hat, frage ich mich, wie es möglich ist, einen Superkonstruktor außerhalb eines Klassenkonstruktors aufzurufen.Wie rufe ich einen Superkonstruktor außerhalb eines Konstruktors auf?

Mein erfolglos naiver Versuch (Ergebnisse in einer Syntax):

class A 
{ 
    constructor() { this.a = 1; } 
} 

function initB() 
{ 
    super(); // How to invoke new A() on this here? 
    this.b = 2; 
} 

class B extends A 
{ 
    constructor() { initB.call(this); } 
} 

Ich bin mir bewusst, dass ein Super-Konstruktor in einer anderen Sprache wie Java kann nur innerhalb des Konstruktor einer abgeleiteten Klasse aufgerufen werden, aber ES6 Klassen sind syntaktischer Zucker für prototypbasierte Vererbung, also würde ich mich wundern, wenn dies mit integrierten Sprachfunktionen nicht möglich wäre. Ich kann einfach nicht die richtige Syntax herausfinden.

Das Beste, was ich mit so gekommen, fühlt sich weit schrecklich wie Betrug:

class A 
{ 
    constructor() { this.a = 1; } 
} 

function initB() 
{ 
    let newThis = new A(); 
    newThis.b = 2; 
    return newThis; 
} 

class B extends A 
{ 
    constructor() { return initB(); } 
} 
+1

Was verhindert, dass Sie den Standard verwenden? Klasse B erweitert A {constructor() {super(); this.b = 2; }} ', wie es sein soll? – Bergi

+0

Ihre "Lösung" ist eigentlich ein Syntaxfehler. – Bergi

+0

@Bergi Ich weiß, mein erster Ansatz ist ein Syntaxfehler, darum frage ich. Ich habe meine Frage geklärt, danke. –

Antwort

6

Jedes Konstruktor einer Klasse, das extends etwas Muss einen direkten super(…) Aufruf enthält.
Direkte super(…) Aufrufe können nur in Konstruktoren platziert werden. Es gibt wirklich keinen Ausweg.

Sie sollten wirklich nicht setzen die Initialisierung Logik einer Klasse irgendwo anders als in seinem Konstruktor. Die einfache und richtige Lösung ist nicht initB überhaupt zu benutzen:

class A { 
    constructor() { this.a = 1; } 
} 

class B extends A { 
    constructor() { 
     super(); 
     this.b = 2; 
    } 
} 

Das heißt, es ist ein Weg, die „super() Aufruf im Konstruktor sein muss“ unterminieren Anforderung. Es zählt auch in eine Pfeilfunktion! So könnten Sie tun

class A { 
    constructor() { this.a = 1; } 
} 

function initB(_super) { 
    var b = _super(); 
    b.b = 2; 
} 
class B extends A { 
    constructor() { 
     initB(() => super()); 
    } 
} 

Versprich mir, dies niemals zu tun, bitte.

Ein anderes Muster ist überhaupt nicht super() aufzurufen, was so lange funktioniert, wie Sie ein Objekt vom Konstruktor zurückgeben. Damit können Sie den eigentlichen Bau des Objekts setzen anderswo:

class A { 
    constructor() { this.a = 1; } 
} 

function makeB() { 
    var b = Reflect.construct(A, [], B); // call the A constructor with B for the prototype 
    b.b = 2; 
    return b; 
} 
class B extends A { 
    constructor() { 
     return makeB(); 
    } 
} 

, die wirklich nicht viel besser ist.

+0

"Es zählt auch eine Pfeilfunktion!" --- Ist es wie im Standard? 'const a =() => {super()};' --- das macht auch Babel irreführend, aber die Möglichkeit zu haben, den Aufruf eines Elternkonstruktors zu vermeiden, wirkt destruktiv: -S – zerkms

+2

Um zu verdeutlichen, ist nur der 'Super'-Aufruf benötigt, wenn Sie 'this' verwenden möchten. aber – Oriol

+0

@Oriol wie etwa [babel/repl] (https://babeljs.io/repl/#?evaluate=true&presets=es2015%2Creact%2Cstage-2&experimental=true&loose=false&spec=true&playground=true&code=class%20A%20% 7B% 0D% 0A% 20% 20% 20% 20Konstruktor()% 20% 7B% 20.a% 20% 3D% 201% 3B% 20% 7D% 0D% 0A% 7D% 0D% 0A% 0D% 0Klasse% 20B% 20Ausdehnungen% 20A% 20% 7B% 0D% 0A% 20% 20% 20% 20Konstrukteur ()% 20% 7B% 0D% 0A% 20% 20% 20% 20% 20% 20% 20% 20Kontakt% 20A% 20% 3D% 20()% 20% 3D% 3E% 20% 7B% 20Super()% 20% 7D% 3B% 0D% 0A% 20% 20% 20% 20% 20% 20% 20% 20Dis.a% 20% 3D% 20T.b% 3B% 0D% 0A% 20% 20% 20% 20% 7D% 0D% 0A% 7D)? – zerkms

Verwandte Themen