2016-06-20 11 views
1

Ich versuche, eine Factory-Funktion, die eine Superklasse und eine Funktion als Argumente akzeptiert, und gibt einen Konstruktor für eine Unterklasse, die überschreibt und wendet einen Filter auf die add() -Methode.Unterklasse Fabrik fehlt Prototyp - Javascript

Das Problem, das ich bekomme, ist, wenn ich diesen Konstruktor verwenden, um dieses Unterklasse-Objekt zu erstellen und add() aufrufen, die add() - Methode wird nicht erkannt.

Wenn es hilft, versuche ich Techniken wie Abschnitt 9.7.2 aus Javascript zu verwenden - Der definitive Leitfaden von David Flanagan.

Schätzen Sie jede Hilfe, danke.

function subclassFactory(superclass,func){ 
    var constructor = function(){ 
     superclass.apply(this,arguments);  

     var proto = constructor.prototype 
        = Object.create(superclass.prototype); 
     proto.constructor = constructor; 

     proto.add = function(){ 
      if(!func(arguments)) 
      { 
       return superclass.prototype.add.apply(this,arguments); 
      } 
     } 
    } 

    return constructor; 
    } 
+0

Möchten Sie Codebeispiel etwas ausmachen, zeigen die Verwendung von 'subclassFactory' für ein Objekt, in dem'() hinzufügen, 'wird nicht erkannt zu werden? –

+1

Sie haben fälschlicherweise die Manipulation von 'constructor.prototype' im Konstruktor. – Bergi

Antwort

3

Ändern Sie nicht den Prototyp im Konstruktor.

Und bitte (als Faustregel) niemals das arguments-object an irgendeine Funktion übergeben.Sie sollten vermeiden, das arguments-Objekt an eine andere Funktion zu übergeben. Es verhindert die Optimierung durch die zugrunde liegende JS-Engine. Verwenden Sie stattdessen den Spread-Operator (ES6 Rest parameters @ MDN) oder kopieren Sie die Argumente manuell in ein Array.

function subclassFactory(superclass, func){ 
    var constructor = function(/*...args*/){ 
     //for(var i=arguments.length,args=Array(i);i--;)args[i]=arguments[i]; 
     //return superclass.apply(this, args); 
     return superclass.apply(this, arguments); 
    } 

    constructor.prototype = Object.create(superclass.prototype, { 
     constructor: { 
      configurable: true, 
      value: constructor 
     }, 
     add: { 
      value: function(/*...args*/){ 
       for(var i=arguments.length,args=Array(i);i--;)args[i]=arguments[i]; 
       if(!func(args)) return superclass.prototype.add.apply(this, args); 
      } 
     } 
    }); 

    return constructor; 
} 

Oder nutzen ES6-Klassen (Classes#Mix-ins @ MDN)

var subclassFactory = (superclass, func) => class extends superclass { 
    add(...args){ 
     if(!func(args)) return super.add.apply(this, args); 
    } 
} 
+0

"nie" ist zu drastisch. Es ist nicht so schlecht im strikten Modus (den Sie sicher verwenden?), Es erfordert nur Instantiierung des Objekts, das ansonsten optimiert werden könnte - aber etwas muss instanziiert werden, um herumgereicht zu werden. Sicherlich ist es in Ihrer "Konstruktor" -Funktion absolut nicht nötig, dieses "args" -Array zu erstellen - in der Tat ist es schneller, "Argumente" direkt an "apply" zu übergeben. – Bergi

+0

@Bergy Du lebst und lernst. Danke. Eigentlich muss ich das nachsehen. Alles, was ich zu diesem Thema gelesen habe, deutet darauf hin, dass das Berühren von Argumenten auf andere Weise als das Zugreifen auf die bekannten Eigenschaften eines der wirklich schlechten Dinge war, die die Engine durch einige Schleifen springen lassen würde, um diese Aufgabe zu sichern und Schäden zu vermeiden Call-Stack, oder so ähnlich.Wenn es nur eine andere Objekt-Instanziierung ist, ist das lächerlich. Hat das Übergeben von Argumenten generell wenig Einfluss, oder gilt das hier nur für den Konstruktor? – Thomas

0

Dies kann passieren, wenn das erste Mal, wenn Sie subclassPrototype anrufen und die superclass Variable nicht ein add Verfahren in seiner Prototypkette:

var parent = subclassFactory(function() {}, function(args) { ... }), 
    child = subclassFactory(parent, function(args) { ... }), 
    childInstance = new child(); 

child.add(...); // throws an exception 

Lösungen:

  1. prüfen für die add-Methode zuerst vor dem Aufruf

  2. immer in einem Super-Klasse-Objekt übergeben, die add irgendwo in seiner Prototypkette

  3. Überprüfen Sie, ob ein Add-Methode in der superClass Prototyp und werfen einen Fehler definiert, wenn man nicht

  4. Wenn die „hinzufügen existiert "Methode existiert nicht in der Superklasse, Standard ist eine leere Funktion