mcpField
M
mixin-pattern

mixin-pattern

github.com/patternsdev开发257617 次安装28 周前更新
代码仓库

关于 mixin-pattern

一项介绍 JavaScript mixin 的技能,可在不建立继承链的情况下为对象或类添加可复用行为。内容说明基于原型的应用方式、适用场景,以及命名冲突和原型污染等风险。

主要功能

  1. 01无需继承即可添加行为
  2. 02使用 Object.assign() 应用属性
  3. 03组合多个 mixin 的行为
  4. 04留意原型污染风险
  5. 05在 React 中优先使用 Hooks

适用场景

  1. 01在多个类间复用方法
  2. 02组合来自不同来源的行为
  3. 03评估 React mixin 的替代方案

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/patternsdev/skills --skill mixin-pattern

安装后在 Claude Code 中输入/mixin-pattern确认已加载。

详细介绍

Mixin 模式

mixin 是一种对象,我们可以用它为另一个对象或类添加可复用的功能,而无需使用继承。我们不能单独使用 mixin:它唯一的用途就是在不使用继承的情况下为对象或类_添加功能_。

假设我们的应用需要创建多只狗。不过,我们创建的基本狗对象除了 name 属性之外没有任何属性。

何时使用

  • 当你需要为多个类添加可复用的功能,但不想创建继承链时,可以使用它
  • 当你想组合来自多个来源的行为时,它会很有用

何时不使用

  • 当使用钩子(React)或组合式函数(Vue)进行组合能达到相同效果且更易追踪时
  • 当存在原型污染风险时——mixin 会修改共享原型,可能导致命名冲突
  • 当要添加的功能足够简单、只需使用工具函数或导入模块即可时

说明

  • 使用 Object.assign() 将 mixin 属性添加到类原型
  • 谨慎处理原型污染——修改原型可能导致意外行为
  • 在 React 中,优先使用 Hooks,而非 mixin(React 团队不建议使用 mixin)
  • 设计可复用行为时,考虑组合而非继承

详情

class Dog {
  constructor(name) {
    this.name = name;
  }
}

狗不应该只有名字,还应该能够吠叫、摇尾巴和玩耍!我们可以创建一个 mixin,为我们提供 bark、wagTail 和 play 属性,而不是直接将它们添加到 Dog 中。

const dogFunctionality = {
  bark: () => console.log("Woof!"),
  wagTail: () => console.log("Wagging my tail!"),
  play: () => console.log("Playing!"),
};

我们可以使用 Object.assign 方法将 dogFunctionality mixin 添加到 Dog 原型。此方法允许我们向_目标对象_添加属性;在本例中,目标对象是 Dog.prototype。每个新的 Dog 实例都可以访问 dogFunctionality 的属性,因为这些属性已添加到 Dog 的原型中!

class Dog {
  constructor(name) {
    this.name = name;
  }
}

const dogFunctionality = {
  bark: () => console.log("Woof!"),
  wagTail: () => console.log("Wagging my tail!"),
  play: () => console.log("Playing!"),
};

Object.assign(Dog.prototype, dogFunctionality);

我们来创建第一只宠物 pet1,名字叫 Daisy。由于我们刚刚将 dogFunctionality mixin 添加到了 Dog 的原型中,Daisy 应该能够行走、摇尾巴和玩耍!

const pet1 = new Dog("Daisy");

pet1.name; // Daisy
pet1.bark(); // Woof!
pet1.play(); // Playing!

太好了!使用 mixin 可以轻松地为类或对象添加自定义功能,而无需使用继承。

虽然我们可以在不使用继承的情况下通过 mixin 添加功能,但 mixin 本身也可以使用继承!

大多数哺乳动物也会行走和睡觉。狗是哺乳动物,因此应该能够行走和睡觉!

我们来创建一个 animalFunctionality mixin,添加 walk 和 sleep 属性。

const animalFunctionality = {
  walk: () => console.log("Walking!"),
  sleep: () => console.log("Sleeping!"),
};

我们可以使用 Object.assign 将这些属性添加到 dogFunctionality 原型中。在本例中,目标对象是 dogFunctionality。

const animalFunctionality = {
  walk: () => console.log("Walking!"),
  sleep: () => console.log("Sleeping!"),
};

const dogFunctionality = {
  bark: () => console.log("Woof!"),
  wagTail: () => console.log("Wagging my tail!"),
  play: () => console.log("Playing!"),
  walk() {
    super.walk();
  },
  sleep() {
    super.sleep();
  },
};

Object.assign(dogFunctionality, animalFunctionality);
Object.assign(Dog.prototype, dogFunctionality);

太好了!现在,任何新的 Dog 实例都可以访问 walk 和 sleep 方法了。

浏览器环境中的 Window 接口就是一个现实世界中的 mixin 示例。Window 对象通过 WindowOrWorkerGlobalScope 和 WindowEventHandlers mixin 实现了许多属性,因此我们能够访问 setTimeout 和 setInterval、indexedDB 以及 isSecureContext 等属性。

由于它是一个 mixin,只用于为对象_添加功能_,因此你无法创建 WindowOrWorkerGlobalScope 类型的对象。

React(ES6 之前)

在引入 ES6 类之前,人们常用 Mixins 为 React 组件添加功能。React 团队不建议使用 Mixins,因为它很容易给组件增加不必要的复杂性,使其难以维护和复用。React 团队建议改用高阶组件,而如今,高阶组件通常可以用 Hooks 替代。

Mixins 通过将功能注入对象的原型,让我们无需继承就能轻松为对象添加功能。修改对象的原型被视为不良实践,因为这可能导致原型污染,并使函数的来源变得难以确定。

来源

参考资料

评论

支持 Markdown