javascriptoopecmascript-6mixinscomposition

How to use mixin in Javascript


Hi everyone I have abstract class Computer:

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);
    }
}
And Desktop class extending the Computer Class. I'm trying to hook mixin functionality to Computer Class, like this:

computerQualityMixin.call(Computer.prototype);

and use it with objects that are of class Desktop. Here is my mixin code;

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);
    };
}
Problem is that I get 'undefined' of all the propertires I try to get:'this.ram' for example in my mixin, when I call some function:

let desktop = new Desktop("JAR Computers", 3.3, 8, 1);
console.log(desktop.getQuality());//Returns NaN because try to make Math operations with 'undefined'

Can someone help me with understanding the mixins? Thanks.


Solution

  • The comments raise good questions about whether you really do want to use mixins here at all. But if you do, you might want to look at the articles by Angus Croll and Reg Braithwaite

    Using the techniques from the former, you could rewrite as

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

    Then you should be able to call those methods on you Computer instances.