Классы ES 6 - Миксины

Я придумываю архитектуру View (разметка HTML) и Utility (JavaScript - поведение) и создаю атомарные классы для составления представлений и утилит с использованием класса ES6. Потребуется, чтобы несколько служебных классов можно было объединить / смешать в один класс представления.

Как может API классов ES6 предоставить способ смешивания класса (ов) с другим / основным классом. Я смотрел Object.assign, но он предназначен для объектов, а не на уровне класса.


person GURU-MVG    schedule 16.08.2016    source источник


Ответы (2)


Классы JavaScript прямо сейчас и, надеюсь, в будущем могут быть расширены друг от друга, но не могут быть смешаны друг с другом. Если да, то, скорее всего, Легкие свойства однажды попадут в спецификацию.

Его архитектурный подход специфичен для JavaScript. В последние несколько лет это упоминалось довольно часто ... esdiscuss.org: »о легких чертах«, github.com/WebReflection: »возможности :: с «, webreflection.blogspot.com: »Утилита классов, дружественная к будущему и обратно совместимая«, reddit.com/r/javascript: »Функциональные миксины в ECMAScript 2015«, raganwald.com: » Функциональные миксины в ECMAScript 2015 « ... и, возможно, лучше всего по сравнению с Полетные миксы.

Подходы Mixin / Trait на основе чистых функций ... Это не эссе на тему «Особенности в Javascript», Множество» талантов «JavaScript ... наиболее близко подходят к тому, о чем просит OP, если только что-то похожее на ...

//  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));

... был отправлен в страну ECMAScript.

person Peter Seliger    schedule 17.08.2016
comment
1/2 - Чтобы доказать описанный выше синтаксис признака, я предоставил библиотеку и, в качестве примера, провел рефакторинг кода четырех других вопросов JavaScript, связанных с признаками, которые ara (1) Композиции и миксины в JS, (2) Миксины для классов ES6, переданные с помощью babel, ... - person Peter Seliger; 04.05.2017

Есть действительно хороший паттерн с классами ES2015 (который я не обязательно одобряю как таковой) для создания миксинов от Себастьяна Markbage, который я немного адаптировал.

Функцию полезности mixinClasses можно использовать для смешивания фабрик классов (также называемых фабричными функциями, возвращающими классы) в ваш новый класс:

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 {});
}

Что можно использовать следующим образом, например, с двумя заводскими функциями Foo и 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();
  }
}
person nils    schedule 17.08.2016