mixin-pattern
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseMixin Pattern
Mixin模式
A mixin is an object that we can use in order to add reusable functionality to another object or class, without using inheritance. We can't use mixins on their own: their sole purpose is to add functionality to objects or classes without inheritance.
Let's say that for our application, we need to create multiple dogs. However, the basic dog that we create doesn't have any properties but a property.
nameMixin是一种对象,我们可以用它在不使用继承的情况下,为其他对象或类添加可复用的功能。Mixin本身无法单独使用:它们的唯一作用就是在不借助继承的前提下,为对象或类添加功能。
假设我们的应用需要创建多个狗的实例。不过我们创建的基础类只有一个属性,没有其他特性。
DognameWhen to Use
使用场景
- Use this when you need to add reusable functionality to multiple classes without creating an inheritance chain
- This is helpful when you want to compose behavior from multiple sources
- 当你需要为多个类添加可复用功能,同时又不想创建继承链时使用
- 当你希望从多个来源组合行为时,这种方式很有帮助
Instructions
实现说明
- Use to add mixin properties to a class prototype
Object.assign() - Be cautious with prototype pollution — modifying prototypes can lead to unexpected behavior
- In React, prefer Hooks over mixins (mixins are discouraged by the React team)
- Consider composition over inheritance when designing reusable behavior
- 使用将Mixin的属性添加到类的原型上
Object.assign() - 要小心原型污染——修改原型可能会导致意外行为
- 在React中,优先使用Hooks而非Mixin(React团队不推荐使用Mixin)
- 在设计可复用行为时,考虑使用组合而非继承
Details
详细示例
js
class Dog {
constructor(name) {
this.name = name;
}
}A dog should be able to do more than just have a name. It should be able to bark, wag its tail, and play! Instead of adding this directly to the , we can create a mixin that provides the , and property for us.
DogbarkwagTailplayjs
const dogFunctionality = {
bark: () => console.log("Woof!"),
wagTail: () => console.log("Wagging my tail!"),
play: () => console.log("Playing!"),
};We can add the mixin to the prototype with the method. This method lets us add properties to the target object: in this case. Each new instance of will have access to the properties of , as they're added to the 's prototype!
dogFunctionalityDogObject.assignDog.prototypeDogdogFunctionalityDogjs
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);Let's create our first pet, , called Daisy. As we just added the mixin to the 's prototype, Daisy should be able to walk, wag her tail, and play!
pet1dogFunctionalityDogjs
const pet1 = new Dog("Daisy");
pet1.name; // Daisy
pet1.bark(); // Woof!
pet1.play(); // Playing!Perfect! Mixins make it easy for us to add custom functionality to classes or objects without using inheritance.
Although we can add functionality with mixins without inheritance, mixins themselves can use inheritance!
Most mammals can walk and sleep as well. A dog is a mammal, and should be able to walk and sleep!
Let's create a mixin that adds the and properties.
animalFunctionalitywalksleepjs
const animalFunctionality = {
walk: () => console.log("Walking!"),
sleep: () => console.log("Sleeping!"),
};We can add these properties to the prototype, using . In this case, the target object is .
dogFunctionalityObject.assigndogFunctionalityjs
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);Perfect! Any new instance of can now access the and methods as well.
DogwalksleepAn example of a mixin in the real world is visible on the interface in a browser environment. The object implements many of its properties from the and mixins, which allow us to have access to properties such as and , , and .
WindowWindowWindowOrWorkerGlobalScopeWindowEventHandlerssetTimeoutsetIntervalindexedDBisSecureContextSince it's a mixin, thus is only used to add functionality to objects, you won't be able to create objects of type .
WindowOrWorkerGlobalScopejs
class Dog {
constructor(name) {
this.name = name;
}
}狗应该能做更多事情,而不只是拥有名字。它应该会吠叫、摇尾巴和玩耍!我们不用直接在类中添加这些功能,而是可以创建一个Mixin来提供、和方法。
DogbarkwagTailplayjs
const dogFunctionality = {
bark: () => console.log("Woof!"),
wagTail: () => console.log("Wagging my tail!"),
play: () => console.log("Playing!"),
};我们可以使用方法把 Mixin添加到的原型上。这个方法可以让我们把属性添加到目标对象中,这里的目标对象就是。每个新创建的实例都能访问的属性,因为它们已经被添加到了的原型上!
Object.assigndogFunctionalityDogDog.prototypeDogdogFunctionalityDogjs
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);让我们创建第一只宠物,名字叫Daisy。由于我们刚刚把 Mixin添加到了的原型上,Daisy应该能够吠叫、摇尾巴和玩耍!
pet1dogFunctionalityDogjs
const pet1 = new Dog("Daisy");
pet1.name; // Daisy
pet1.bark(); // Woof!
pet1.play(); // Playing!完美!Mixin让我们不用继承就能轻松为类或对象添加自定义功能。
虽然我们可以通过Mixin在不使用继承的情况下添加功能,但Mixin本身也可以使用继承!
大多数哺乳动物都会走路和睡觉。狗是哺乳动物,也应该具备这些能力!
让我们创建一个 Mixin,添加和方法。
animalFunctionalitywalksleepjs
const animalFunctionality = {
walk: () => console.log("Walking!"),
sleep: () => console.log("Sleeping!"),
};我们可以用把这些属性添加到的原型上,这里的目标对象是。
Object.assigndogFunctionalitydogFunctionalityjs
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);完美!现在任何新的实例都能访问和方法了。
Dogwalksleep现实世界中Mixin的一个例子是浏览器环境中的接口。对象的许多属性都是从和这两个Mixin实现的,这让我们可以访问、、和等属性。
WindowWindowWindowOrWorkerGlobalScopeWindowEventHandlerssetTimeoutsetIntervalindexedDBisSecureContext由于它们是Mixin,因此只能用来为对象添加功能,你无法创建类型的对象。
WindowOrWorkerGlobalScopeReact (pre ES6)
React(ES6之前)
Mixins were often used to add functionality to React components before the introduction of ES6 classes. The React team discourages the use of mixins as it easily adds unnecessary complexity to a component, making it hard to maintain and reuse. The React team encouraged the use of higher order components instead, which can now often be replaced by Hooks.
Mixins allow us to easily add functionality to objects without inheritance by injecting functionality into an object's prototype. Modifying an object's prototype is seen as bad practice, as it can lead to prototype pollution and a level of uncertainty regarding the origin of our functions.
在ES6类引入之前,Mixin常被用于为React组件添加功能。React团队不推荐使用Mixin,因为它很容易给组件添加不必要的复杂度,使其难以维护和复用。React团队当时鼓励使用高阶组件,而现在高阶组件通常可以被Hooks替代。
Mixin允许我们通过向对象原型注入功能,在不使用继承的情况下轻松为对象添加功能。不过修改对象原型被视为不良实践,因为这可能导致原型污染,并且会让我们对函数的来源产生不确定性。
Source
来源
References
参考资料
- Functional Mixins - Eric Elliott
- Mixins - JavaScript Info
- Functional Mixins - Eric Elliott
- Mixins - JavaScript Info