大家好我有抽象类电脑:
class Computer {
constructor(manufacturer, processorSpeed, ram, hardDiskSpace) {
if (new.target === Computer) {
throw new Error("Cannot instantiate directly.");
}
this.manufacturer = manufacturer;
this.processorSpeed = Number(processorSpeed);
this.ram = Number(ram);
this.hardDiskSpace = Number(hardDiskSpace);
}
}
computerQualityMixin.call(Computer.prototype);
并将其与Desktop类对象一起使用。这是我的mixin代码;
function computerQualityMixin() {
let ram = this.ram;
let processorSpeed = this.processorSpeed;
let hardDiskSpace = this.hardDiskSpace;
this.getQuality = () => {
return processorSpeed
* ram
* hardDiskSpace;
};
this.isFast = () => {
return processorSpeed > ram / 4;
};
this.isRoomy = () => {
return hardDiskSpace > Math.floor(ram * processorSpeed);
};
}
let desktop = new Desktop("JAR Computers", 3.3, 8, 1);
console.log(desktop.getQuality());//Returns NaN because try to make Math operations with 'undefined'
有人可以帮助我理解mixins吗?谢谢。
答案 0 :(得分:0)
这些评论提出了一个很好的问题,即你是否真的想在这里使用mixins。但是,如果您这样做,您可能希望按Angus Croll和Reg Braithwaite
查看文章使用前者的技术,您可以重写为
const asComputerQuality = function() {
this.getQuality = function() {
return this.processorSpeed
* this.ram
* this.hardDiskSpace;
};
this.isFast = function() {
return this.processorSpeed > this.ram / 4;
};
this.isRoomy = function() {
return this.hardDiskSpace > Math.floor(this.ram * this.processorSpeed);
};
}
asComputerQuality.call(Computer.prototype);
然后您应该能够在Computer
个实例上调用这些方法。
答案 1 :(得分:0)
应该将Mixins视为一种方便的代码重用形式。
描述对象的某些行为的代码 往往会被一遍又一遍地复制,可能会被考虑 被收集/存储一次到混合物中。
使用JavaScript中基于函数的mixin / trait模式 人们也可以利用其提供的有状态变体 人们可能会如何安排更多的可能性 一种类型/对象架构。
正如已经指出的那样,OP的例子并不是那么好 根据基于mixin / trait的组合物的选择而选择。
然而,下一个给定的代码块确实稍微尝试了 改变了变体以展示不同的方法 在JavaScript中应用基于函数的mixin / trait模式...
function withObjectBaseIntrospection(state) { // - mixin that preserves injected
var // local state by creating a
object = this; // closure at call/apply time.
object.valueOf = function () {
return Object.assign({}, state);
};
object.toString = function () {
return JSON.stringify(state);
};
}
function withHardwareStandardGetters(state) { // - mixin that preserves injected
var // local state by creating a
hardware = this; // closure at call/apply time.
Object.defineProperty(hardware, "manufacturer", {
get: function () { return state.manufacturer; }
});
Object.defineProperty(hardware, "processorSpeed", {
get: function () { return state.processorSpeed; }
});
Object.defineProperty(hardware, "ram", {
get: function () { return state.ram; }
});
Object.defineProperty(hardware, "hardDiskSpace", {
get: function () { return state.hardDiskSpace; }
});
}
function withDesktopSpecificGetters(state) { // - mixin that preserves injected
var // local state by creating a
hardware = this; // closure at call/apply time.
Object.defineProperty(hardware, "bodyLength", {
get: function () { return state.bodyLength; }
});
Object.defineProperty(hardware, "bodyWidth", {
get: function () { return state.bodyWidth; }
});
Object.defineProperty(hardware, "bodyHeight", {
get: function () { return state.bodyHeight; }
});
}
function withHardwareSpecificQuality() { // - generic function based mixin pattern.
this.getQuality = function() {
return (this.processorSpeed * this.ram * this.hardDiskSpace);
};
this.isFast = function () {
return (this.processorSpeed > (this.ram / 4));
};
this.isRoomy = function () {
return (this.hardDiskSpace > Math.floor(this.ram * this.processorSpeed));
};
}
function withDesktopSpecificMeasures() { // - generic function based mixin pattern.
this.getBodyVolume = function() {
return (this.bodyLength * this.bodyWidth * this.bodyHeight);
};
}
class Computer {
constructor(state) {
withObjectBaseIntrospection.call(this, state); // - applying 2 "stateful mixin"
withHardwareStandardGetters.call(this, state); // at instance/object level.
}
}
withHardwareSpecificQuality.call(Computer.prototype); // - making use of inheritance via the
// constructor's prototype, but enriching the
// latter by a more generic mixin (at "class level").
class Desktop extends Computer { // - newly available
constructor(state) { // syntactic sugar for the more
// "class like" inheritance pattern.
super(state);
withDesktopSpecificGetters.call(this, state); // - applying a "stateful mixin"
} // at instance/object level.
}
withDesktopSpecificMeasures.call(Desktop.prototype); // - making use of inheritance via the
// constructor's prototype, but enriching the
// latter by a more generic mixin (at "class level").
let
desktop = new Desktop({
manufacturer: "JAR Computers",
processorSpeed: 3.3,
ram: 8,
hardDiskSpace: 1,
bodyWidth: 300,
bodyHeight: 40,
bodyLength: 300
});
console.log("Desktop.prototype : ", Desktop.prototype);
console.log("Computer.prototype : ", Computer.prototype);
console.log("(desktop instanceof Desktop) ? ", (desktop instanceof Desktop));
console.log("(desktop instanceof Computer) ? ", (desktop instanceof Computer));
console.log("desktop.manufacturer : ", desktop.manufacturer);
console.log("desktop.processorSpeed : ", desktop.processorSpeed);
console.log("desktop.ram : ", desktop.ram);
console.log("desktop.hardDiskSpace : ", desktop.hardDiskSpace);
console.log("desktop.getQuality() : ", desktop.getQuality());
console.log("desktop.getBodyVolume() : ", desktop.getBodyVolume());
console.log("desktop.valueOf() : ", desktop.valueOf());
console.log("desktop.toString() : ", desktop.toString());
有人可能会考虑查看一个更好的JavaScript示例,也会尝试演示when to use inheritance via class extension and when not, when to use just mixin/trait based composition and also when to use both。
旁注 - 关于JavaScript中的Mixins / Traits / Talents函数的推荐资源
此外,我建议阅读我在SO上给出的一些列出的答案,这些答案也与此主题相关。