2016-11-06 64 views
-2
大家

您好我有抽象類計算機:如何使用混入在Javascript

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); 
 
    } 
 
}
和擴展計算機類桌面類。 我試圖鉤的mixin功能,計算機類,像這樣:

computerQualityMixin.call(Computer.prototype);

,並與有級桌面的對象使用它。這裏是我的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); 
 
    }; 
 
}
問題是,我得到的所有propertires的「未定義」我試圖讓:「this.ram」例如在我的mixin,當我打電話了一些功能:

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

有人能幫我理解mixin嗎?謝謝。

+3

我想你應該如何別的之前使用堆棧溢出片段閱讀...... –

+0

你怎麼定義'Desktop'? 'Computer.prototype'上定義了'ram','processorSpeed'和'hardDiskSpace'?如果沒有,爲什麼你把'computerQualityMixin'作爲'this'值傳遞'Computer.prototype'呢? – Oriol

+1

'Computer.prototype'是空的對象。如果代碼應該按預期工作,應該在構造函數的末尾調用'computerQualityMixin.call(this)'。整個'mixin'的東西看起來很混亂。由於'計算機'沒有父親,我沒有看到爲什麼它不能在自己或父類中定義'getQuality'等方法。 – estus

回答

0

評論提出了很好的問題,關於你是否真的想在這裏使用mixins。但是,如果你這樣做,你可能想通過Angus CrollReg 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實例。

0

Mixins應該被看作是代碼重用的一個方便的形式。描述對象的某種行爲,也

代碼往往是複製了一遍又一遍,可能被認爲是收集/一次存儲到一個混合的 。

在JavaScript中 一個也基於功能的mixin /特徵的圖案可以利用其狀態的變體,提供 更有人可能會如何去安排 那些類型/對象體系結構(S)的可能性。

正如已經指出的那樣,OP的例子並不是 所選擇的適合mixin/trait的組合。

下一個給定的代碼塊仍然沒有一個稍微 改變變種試圖以展示不同的方法在JavaScript應用基於函數的mixin /特質模式 ...

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

側面說明 - 功能上從2014年4月自2011年

  • The many talents of JavaScript for generalizing Role Oriented Programming approaches like Traits and Mixins可以根據混入/特徵/人才在JavaScript

    此外,我倒建議閱讀SO上列出的一些列出的與本主題相關的答案。