【问题标题】:ES 6 Classes - MixinsES 6 类 - Mixins
【发布时间】:2016-12-22 13:30:58
【问题描述】:

我正在提出视图(HTML 标记)和实用程序(JavaScript - 行为)架构,并创建原子类以使用 ES6 类来组合视图和实用程序。需要将多个实用程序类组合/混合到一个视图类中。

ES6 Class API 如何提供一种将类混入另一个/主类的方法。我看过Object.assign,但那是针对对象而不是在类级别。

【问题讨论】:

    标签: javascript ecmascript-6 mixins traits


    【解决方案1】:

    现在的 JavaScript 类,希望将来也能 只能互相延伸,不能混用 成彼此。如果有的话,那么很可能 轻量级特征 一定要在某一天将其纳入规范。

    它的架构方法是特定于 JavaScript 的。它 近几年经常被提及... 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« ... 并且可能与 Angus Croll 的 Flight Mixins 相比最好。

    基于纯函数的 Mixin/Trait 方法 ...This is not an essay about 'Traits in Javascript', The many »Talents« of 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 土地。

    【讨论】:

    【解决方案2】:

    ES2015 类有一个非常好的模式(我不一定赞同这样)来创建 mixins by Sebastian 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 {});
    }
    

    可以如下使用,例如两个工厂函数FooBar

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

    【讨论】:

      猜你喜欢
      • 2015-03-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-07-06
      • 2016-07-13
      • 1970-01-01
      相关资源
      最近更新 更多