2016-08-16 25 views
0

Ich entwerfe die Architektur von View (HTML Markup) und Utility (JavaScript - Behavior) und erstelle atomare Klassen für das Erstellen von Sichten und Dienstprogrammen mit ES6 Class. Es wird notwendig sein, dass mehrere Nutzklassen zu einer einzigen Sichtklasse zusammengesetzt/gemischt werden können.ES 6 Klassen - Mixins

Wie kann die ES6-Klassen-API eine Möglichkeit bieten, Klassen in eine andere/Hauptklasse einzumischen? Ich habe Object.assign betrachtet, aber das ist für Objekte und nicht auf Klassenebene.

Antwort

2

JavaScript-Klassen jetzt und hoffentlich auch in Zukunft können nur voneinander erweitert werden, aber nicht gemischt werden ineinander. Wenn überhaupt, dann wahrscheinlich Leichte Eigenschaften machen es in die Spezifikation eines Tages.

Der Architekturansatz ist spezifisch für JavaScript. Es wurde in den letzten Jahren sehr oft erwähnt ... esdiscuss.org: »about lightweight traits«, github.com/WebReflection: »features :: with«, webreflection.blogspot.com: »A future friendly, backward compatible, class utility«, reddit.com/r/javascript: »Functional Mixins in ECMAScript 2015« , raganwald.com: »Functional Mixins in ECMAScript 2015« ... und möglicherweise am besten im Vergleich zu Angus Crolls Flight Mixins.

reine Funktion basiert Mixin/Trait nähert sich ... This is not an essay about 'Traits in Javascript', The many »Talents« of JavaScript ... do am nächsten kommen, was die OP für es sei denn, etwas fragen hat ähnlich wie ...

// proposed trait syntax ...  // ... desugared e.g. to ... 

trait Enumerable_first_last {  // var Enumerable_first_last = (function() { 
    // trait body.     // // mixin module. 
            // 
    const        // var 
    FIRST = function() {   //  first = function() { // shared code. 
     return this[0];    //  return this[0]; 
    },        //  }, 
    LAST = function() {   //  last = function() { 
     return this[this.length - 1]; //  return this[this.length - 1]; 
    }        //  } 
    ;         // ; 
            // 
    applicator() {     // return function Enumerable_first_last() { 
    // applicator body.    //  // mixin body. 
            // 
    this.first = FIRST;    //  this.first = first; // referencing ... 
    this.last = LAST;    //  this.last = last; // ... shared code. 
    }         // }; 
            // 
}         // }()); 

...

// proposed trait syntax ...  // ... desugared e.g. to ... 

trait Enumerable_item {    // var Enumerable_item = (function() { 
            // 
    const        // var 
    ITEM = function (idx) {   //  item = function (idx) { 
     return this[     //  return this[ 
     Math.floor(    //   Math.floor(
      parseFloat(idx, 10)  //   parseFloat(idx, 10) 
     )       //   ) 
     ];       //  ]; 
    }        //  } 
    ;         // ; 
            // 
    applicator() {     // return function Enumerable_item() { 
            // 
    this.item = ITEM;    //  this.item = item; 
    }         // }; 
            // 
}         // }()); 

...

// proposed trait syntax ...  // ... desugared e.g. to ... 

trait Enumerable_first_last_item { // var Enumerable_first_last_item = (function() { 
            // 
    use Enumerable_first_last;  // return function Enumerable_first_last_item() { 
    use Enumerable_item;    // 
/*         //  Enumerable_first_last.call(this); 
    applicator() {     //  Enumerable_item.call(this); 
    // can be omitted if empty.  // }; 
    }*/        // 
}         // }()); 

...

         // ... desugared e.g. to ... 
             // 
class Queue {       // var Queue = (function() { 
             // 
//use Allocable;      // return function Queue() { 
    use Observable;      //  var list = []; 
             // 
    constructor() {     //  this.enqueue = function (type) { 
    const list = [];     // 
             //  list.push(type); 
    this.enqueue = function (type) { //  return type; 
             //  }; 
     list.push(type);    //  this.dequeue = function() { 
     return type;     // 
    };        //  return list.shift(); 
    this.dequeue = function() {  //  }; 
             // 
     return list.shift();   // //Allocable.call(this, ...); 
    };        //  Observable.call(this); 
    }         // }; 
             // 
}          // }()); 
             // 
var q = new Queue;     // var q = new Queue; 
             // 
q.enqueue(9);       // q.enqueue(9); 
q.enqueue(8);       // q.enqueue(8); 
q.enqueue(7);       // q.enqueue(7); 
             // 
console.log(q.dequeue());    // console.log(q.dequeue()); 
console.log(q.dequeue());    // console.log(q.dequeue()); 
console.log(q.dequeue());    // console.log(q.dequeue()); 
             // 
console.log(q);      // console.log(q); 
console.log(Object.keys(q));   // console.log(Object.keys(q)); 

... wurde zu ECMAScript Land verschifft.

+0

1/2 - um das oben skizzierte trait Syntax zu beweisen I eine lib zur Verfügung gestellt und haben beispielhaft den Code von 4 anderen Trait umgestalten zu verwandten JavaScript Qs, die ara (1) [Com Positionen und Mixins in JS] (http://stackoverflow.com/questions/41999608/compostions-and-mixins-in-js/43141778#43141778), (2) [Mixins für ES6-Klassen, mit Babel transpiliert] (http: //stackoverflow.com/questions/30732241/mixins-for-es6-classes-translated-with-babel/43129978#43129978), ... –

+0

2/2 - (3) [Refactoring von Legacy-Mixin-basierten Klassenhierarchien] (http://stackoverflow.com/questions/43027388/refactoring-legacy-mixin-based-class-hiericharies/43059101#43059101) und (4) [Mehrfachvererbung mit Klassen] (http://stackoverflow.com/questions/41918874/multiple-inheritance-using-classes/43748183#43748183). –

2

Es gibt ein wirklich schönes Muster mit ES2015-Klassen (die ich nicht unbedingt als solche befürworte), um Mixins by Sebastian Markbage zu erstellen, die ich leicht angepasst habe.

Die Nutzenfunktion mixinClasses kann verwendet werden, in der Klasse Fabriken (auch bekannt als Fabrik-Funktionen, die Klassen zurück) in die neue Klasse zu mischen:

function mixinClasses(...mixins) { 
    // TODO: Add all possible method names that might call super() 
    // to the base class so that they don't throw. 
    return mixins.reduce((base, mixin) => { 
     return mixin(base); 
    }, class {}); 
} 

, die wie folgt, wobei die beiden Werksfunktionen beispielsweise verwendet werden können, Foo und Bar:

const Foo = base => class extends base { 
    myFn() { 
    } 
}; 

const Bar = base => class extends base { 
    myFn() { 
    super.myFn(); 
    } 
}; 

class Baz extends mixinClasses(Foo, Bar) { 
    myFn() { 
    super.myFn(); 
    } 
}