JavaScript 的 Mixin 问题

JavaScript 从 ES6 开始支持 class 了, 如何在现在的 class 上实现 mixin 呢? 很多人推荐这种搞法

Object.assign(MyClass.prototype, MyMixin);

这个做法很丑, 不能令人满意。

我找到了一个更有趣的做法,和 dart 比较接近:

"Real" Mixins with JavaScript Classes

他最终的做法是这样的:

class MyClass extends mix(MyBaseClass).with(Mixin1, Mixin2) {
  /* ... */
}

Mixin1 Mixin2 的定义是

let Mixin1 = (superclass) => class extends superclass {
  foo() {
    console.log('foo from Mixin1');
    if (super.foo) super.foo();
  }
};

let Mixin2 = (superclass) => class extends superclass {
  foo() {
    console.log('foo from Mixin2');
    if (super.foo) super.foo();
  }
};

class S {
  foo() {
    console.log('foo from S');
  }
}

class C extends Mixin1(Mixin2(S)) {
  foo() {
    console.log('foo from C');
    super.foo();
  }
}

new C().foo();

要点是 class 在 js 里性质和 function 相似, 都具有闭包性, 因此可以通过函数构造出来.

说到这个前两天根据我们需要什么样的 ORM 框架 - Inshua - 博客园的思考, 正好试验了这个特征:

function nvarchar(n){
    return class{
        constructor(){
            this.size = n;
        }
    }
}
var t = nvarchar(200);
var c = new t();

看起来效果还可以, 但是 JavaScript 变量不支持类型, 所以目前还无法发挥它的实力.

Flow 和 TypeScript 能给 JavaScript 添加类型, 但都没有很好的往这个方向走. Dart 就不用考虑了, class 不能定义在 function 里, 也不能作为值使用. 可能裁剪的 TypeScript 是比较适当的选择, 但是我不想使用这种生成 js 的套盒语言.

posted @ 2024-04-19 16:15  Inshua  阅读(30)  评论(0编辑  收藏  举报