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());