【问题标题】:Composition and Mixins with JavaScript使用 JavaScript 组合和混合
【发布时间】:2019-10-17 04:46:18
【问题描述】:

我正在学习 Javascript 中的组合。所以我想问一下这是否是正确的做事方式。

我做了一些看起来像这样的练习:

    class Animal {
    // constructor() {
    // }
    eat = () => {
        console.log("this creature is eating");
    }
}

const AnimalsWithWings = superclass => class extends superclass {
    constructor(Feathers, ...args) {
        super(...args);
        Object.assign(this, { Feathers });
    }
}

const CanDive = superclass => class extends superclass {
    // constructor( ...args) {
    //     super(...args);
    // }
    dive = () => {
        console.log("Can Dive");
    }
}

class Duck extends AnimalsWithWings(CanDive(Animal)) {
    constructor(eats, ...args) {
        super(...args);
        Object.assign(this, { eats });
    }
}

const duffy = new Duck("watermelon", true);
console.log(duffy);

duffy.dive();
duffy.eat()

我还在学习过程中,所以我只需要一些指示。

【问题讨论】:

  • 你运行了吗?

标签: javascript multiple-inheritance


【解决方案1】:

它或多或少地达到了您的预期?那么,当然,这是一种正确的方法,无论“正确”在这里是什么意思。

在我看来,当我将它弹出到控制台时,它就像它应该做的那样。我真的不能对你的代码说更多,因为我不确定它试图建模的具体域,除了可能将 Ducks 分解成原子片段。

但是,如果您打算这样做,我个人更喜欢使用 params 对象,而不是像 AnimalsWithWings 那样更改构造函数签名。这样,额外参数化的顺序不取决于应用混入的顺序,我认为这是一个惊喜。惊喜是不好的。

const AnimalsWithWings = superclass => class extends superclass {
    // Everyone receives the same `params` object.
    // They only take what they know about, and ignore the rest.
    constructor(params) {
        super(params);
        Object.assign(this, { Feathers: params.Feathers });
    }
}

更个人观点,我将它们命名为 WithDivingWithWings,只是为了保持命名方案的一致性,并更好地暗示这些是修饰符,而不是“真正的”基类。

您的代码确实为每个 Duck 提供了一个原型链 4 个原型,但是,无论如何。如果它以某种方式成为性能问题,那么您可以创建一个实用程序函数来优化 mixin 过程或其他东西。或许可以将原型展平。

您的代码还允许您在方法中调用 super.method(),尽管您是否应该在 mixin 中使用它是有争议的。我会说你不应该,除非你希望你的 mixin 隐式地相互依赖,这是一个惊喜。

还有很多其他的混合方式。

  • 您可以创建一个实用函数来将所有原型扁平化为一个新原型,并从您扩展的原型中返回一个基类。 (如果您想正确处理get/set 访问器等内容,请确保在进行扁平化时迭代属性描述符而不是仅使用Object.assign()
  • 您可以避开类,直接创建原型对象并使用Object.create() 创建实例。 (迭代属性描述符也是如此。)
  • 您可以使用对 Object.create() 的大量迭代调用来创建 Duck 原型,而不是迭代扩展基类。
  • 您可以使用辅助控制器类来控制其他行为,而不是将行为直接组合到基础中。
  • 您可以只处理带有数据的普通对象,然后将对象传递给期望对象具有某些属性的函数以执行操作。 (有趣的是,称为“鸭子打字”)我承认这不是真正的混合,只是调用函数,但如果它实际上完成了同样的事情......
  • 可能还有一堆我现在想不起来的。都是将一系列行为粘在一些基本事物上。

【讨论】:

  • 非常感谢您的详尽回答。这对我帮助很大。祝你有美好的一天!
猜你喜欢
  • 2020-03-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-09-18
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多