通过遍历 class(原型)属性使 Mixins 工作

Make Mixins work by looping through a class (prototype) properties

我使用 Coffeescript 有一段时间了...我一直在使用的东西是 mixins,我从这个 article 中得到启发,这是 class 我用 coffeescript :

class @Module

    @extend: (obj) ->

        for key, value of obj

            # will be available as class methods

            @[key] = value

        this


    @include: (obj) ->

        for key, value of obj

            # Assign properties to the prototype

            @::[key] = value # similar to this.prototype[key] = value

        this

includeclass方法复制一个obj(基本上是另一个class)方法,并使它们成为目标class的实例方法,而extend 方法将使 obj 方法作为目标 class 的 class 方法。

这个class的用法很简单:

class @TargetClass extends Module

    @include Class1::
    @extend Class2::

}

现在我正在转向 ES6 语法,我正在尝试将该语法转换为原始语法 javascript,这是我的模块 class:

export class Module {

    static extend(obj) {

        for (let key in obj) {

            // will be available as class methods

            const value = obj[key];
            this[key] = value;
        }

        return this;
    }


    static include(obj) {

        for (let key in obj) {

            // Assign properties to the prototype

            const value = obj[key];
            this.prototype[key] = value;
        }

        return this;
    }
};

然后我试图让 Class1 的方法在我的 TestClass 中作为实例方法可用:

这是我的 Class1:

export Class1{
  tobe_mixed_func(){
    console.log("it should works");
  }
}

这是我的测试类:

import { Module } from "./module"
import { Class1 } from "./class1"

class TestClass extends Module{
  static initClass(){
    this.include(Class1.prototype) // I also tried this.include(Class1) but doesn't work either
  }
}

TestClass.initClass();

TestClass.tobe_mixed_func(); //  TestClass.tobe_mixed_func is not a function

我收到 TestClass.tobe_mixed_func is not a function 错误,我尝试调试以查看我的 Module.include 函数是否在 obj 参数中接收到 Class1,它接收到了!但是我注意到的是 Module.includefor (let key in obj) {...} 部分不会循环抛出 class "keys" 在这种情况下应该是 "tobe_mixed_func"

我放了一个 console.log(key) 来查看这样的输出:

static include(obj) {

  for (let key in obj) {

    console.log(key);

     const value = obj[key];
     this.prototype[key] = value;
  }

  return this;
}

但是 For 循环永远不会执行...有人能看出我遗漏了什么吗?

函数不可枚举,因此在您执行 for..in 时不会列出。您需要 getOwnPropertyNames 来复制它们:

function assignAll(target, source) {
    for (let p of Object.getOwnPropertyNames(source))
        target[p] = source[p];
}


class Module {
    static extend(obj) {
        assignAll(this, obj);
    }

    static include(cls) {
        assignAll(this.prototype, cls.prototype);
    }
}


class Class1 {
    tobe_mixed_func() {
        console.log("it should work");
    }
}


class TestClass extends Module {
    static initClass() {
        this.include(Class1)
    }
}


TestClass.initClass();

let a = new TestClass();

a.tobe_mixed_func()

至于更好的方法,我会定义一个普通函数(不是方法),像这样

function mixin(target, ...sources) {
    for (let src of sources)
        for (let p of Object.getOwnPropertyNames(src.prototype))
            target.prototype[p] = src.prototype[p];
    return target;
}

然后像这样声明 mixins

 class MyClass {
    ...
 }

 mixin(MyClass, SomeMixin, SomeOtherMixin)

甚至

const MyClass = mixin(class {
   ...
}, SomeMixin, SomeOtherMixin)