本文由 简悦SimpRead 转码,原文地址 www.digitalocean.com
快速浏览一下JavaScript混合器以及如何在类中使用它们。
说到高级类的组成,JavaScript有相当多的方法--一个真正的大杂烩式的选择。有一种类型的模式在野外很少被发现,那就是基于混血的继承模式。混合体通常会被新的JavaScript程序员跳过(我也这样做过)。我不想抱怨,但混合器的编写和理解有时是相当密集的。但是它们有一堆值得研究的特性。
mixin模式--顾名思义--是一种将一个对象与其他对象混合在一起的模式,以增加我们需要的属性。把它想成是可以给你的对象提供额外属性的附加组件,但这些单独的属性本身并不是真正的子类。
从表面上看,mixins的行为就像对象的混合层,我们把目标(mixin)和源传递进去。目标被附加到源上,然后返回一个新的对象。
更准确的描述是,mixin像工厂一样工作,新的子类对象被返回。在这整个过程中,没有任何地方对子类进行定义。
一个更像C++的比喻是把它们比作带有虚拟函数的抽象类,允许它们被其他子类继承。
所以,现在我们知道mixins允许我们创建一个修改过的定义,可以应用于现有的超类来创建新的子类,让我们看看mixin会是什么样子。
//The swim property here is the mixin
let swim = {
location() {
console.log(`Heading ${this.direction} at ${this.speed}`);
}
};
let Alligator = function(speed, direction) {
this.speed = speed,
this.direction = direction
};
//This is our source object
let alligator = new Alligator('20 mph','North');
alligator = Object.assign(alligator, swim);
console.log(alligator.location());
在上面的片段中,我们想创建一个会游泳的鳄鱼。所以我们创建一个新的alligator',然后给它赋予swim'功能。swim对象是我们希望alligator对象使用Object.assign方法拥有的混合体或扩展。
Object.assign方法允许我们一次添加一个以上的混合器。一个多混合器的情况会是这样的。
alligator = Object.assign(alligator, swim, crawl);
现在让我们看看混合器如何与ES6类一起使用。
let swim = {
setSwimProperties(speed, direction) {
this.speed = speed;
this.direction = direction;
},
getSwimProperties(){
console.log(`swimming ${this.speed} towards ${this.direction}`);
}
}
class Reptile {
constructor(name) {
this.name = name;
}
}
Object.assign(Reptile.prototype, swim);
let alligator = new Reptile("alligator");
alligator.setSwimProperties("5 m/s", "upstream");
alligator.getSwimProperties();
通过mixin方法添加功能的优势在于灵活性。mixin是一个非常原始的函数,因为它只做一件事,所以我们可以在各种情况下重复使用这些结构。它可以与本地函数调用一起使用,也可以在类定义中使用,等等。
另一个好处是,它倾向于保持类的层次结构水平--通过允许超类使用混合器来创建所需的子类属性的新对象,而不是让继承链更长,以便为这些情况创建新的子类。
不过在使用混集函数时要注意一些事情。
Object.assign(在对象和类的实现中)只做了一个混合属性的浅层拷贝。- 在使用来自不同混合体的属性时,可能会有潜在的名称冲突(多重继承中的钻石问题)。
- 由于属性被复制到源对象上,要弄清属性来自哪个混合体可能相当困难。
instanceof操作符在这里不能帮助我们。