2012-11-29 91 views
5

我正在組織一個小型企業應用程序,但希望儘可能幹。結果,我一直在看mixin庫。如何在Javascript中正確使用mixins

我遇到了這個library,並認爲這可能是一個不錯的選擇,因爲它允許你在運行時混合進出。另外,我可以只有一個基類(BaseView),例如只是混入其中。

問題

  1. 什麼是有用的混入的一些實際應用的例子嗎? (請不要再抽象的例子)
  2. 我是否甚至需要擴展類,或者我可以使用這個庫來管理所有擴展和混合?

回答

2

一個混入僅僅是一個不同的概念想法如何組織代碼和繼承。您當然可以將它與經典原型繼承結合使用,但它也可以獨立工作,可以這麼說。

例如,而不是創建「下放」對象屬性/查找(如原型繼承),我們將真正「形式」新的獨立的對象,從多個其他對象。這也有時稱爲「多重繼承」,並且單獨使用Javascript 原型繼承不能輕易實現。

舉個例子:

var pianist = { 
    play: function() {} 
}; 

var programmner: { 
    code: function() {} 
}; 

而現在,我們可以創建另一個對象,像

var Jim = Object.create(null); // create a fully self-defining object 

extend(Jim, pianist); 
extend(Jim, programmer); 

這種僞extend方法可能看上去像(ES5):

function extend(target, source) { 
    Object.getOwnPropertyNames(source).forEach(function(key) { 
     Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)) }); 

    return target 
} 

我其實沒有正確回答你的問題,但我覺得沒有真正回答你的問題。它和你要使用它一樣真實,沒有真正的「特定應用」用例。

3

另請參見:

如果涉及到JavaScript和基於角色組成接近像混入和特點,我同時非常固執己見。我總是將指向2個純函數基於圖案庫不可知組合 - 首先模塊模式二的「飛行密新」模式,因爲它已被重新發現,命名和安格斯·克羅爾在2011年5月描述,但我也建議閱讀礦從2014年4月紙

問題

  • 1)什麼是有用的Mixins的一些真正的應用實例? (請沒有更抽象的例子)
  • 2)我甚至需要擴展類或者我可以只使用這個庫來管理所有的擴展和混入?

回答你的2個問題...

月1日)[Observable]可能是對混入最常見的現實世界的例子之一。但是這不是提供完整代碼庫的正確地方。來自Smart Talents chapter的相繼增長的例子確實提供了[Queue]工廠的工作實施,其在開始時僅使用不同的Mixins,如[Enumerable][Allocable],但最終也適用於已經提到的[Observable]

2日)就利用你的選擇還是需要的模塊系統 - CommonJS or AMD。您的工廠模塊或甚至實例/對象會通過委派檢索其他行爲;因此,它們積極地做call/apply密新性狀模塊。

最後 - 縮短示例代碼:

var Observable_SignalsAndSlots = (function() { 
 

 
    var 
 
    Event = function (target, type) { 
 

 
     this.target = target; 
 
     this.type = type; 
 
    }, 
 

 
    EventListener = function (target, type, handler) { 
 

 
     var defaultEvent = new Event(target, type); 
 

 
     this.handleEvent = function (evt) { 
 
     /* ... */ 
 
     }; 
 
     this.getType = function() { 
 
     return type; 
 
     }; 
 
     this.getHandler = function() { 
 
     return handler; 
 
     }; 
 
    }, 
 

 
    EventTargetMixin = function() { 
 

 
     var eventMap = {}; 
 

 
     this.addEventListener = function (type, handler) { 
 
     /* ... */ 
 
     }; 
 
     this.dispatchEvent = function (evt) { 
 
     /* ... */ 
 
     }; 
 
    } 
 
    ; 
 

 
    return EventTargetMixin; 
 

 
}).call(null); 
 

 

 
var Queue = (function() { 
 

 
    var 
 
    global = this, 
 

 
    Observable = global.Observable_SignalsAndSlots, 
 
    //Allocable = global.Allocable, 
 

 
    Queue, 
 

 
    onEnqueue = function (queue, type) { 
 
     queue.dispatchEvent({type: "enqueue", item: type}); 
 
    }, 
 
    onDequeue = function (queue, type) { 
 
     queue.dispatchEvent({type: "dequeue", item: type}); 
 
    }, 
 
    onEmpty = function (queue) { 
 
     queue.dispatchEvent("empty"); 
 
    } 
 
    ; 
 

 
    Queue = function() { // implementing the [Queue] Constructor. 
 
    var 
 
     queue = this, 
 
     list = [] 
 
    ; 
 
    queue.enqueue = function (type) { 
 

 
     list.push(type); 
 
     onEnqueue(queue, type); 
 

 
     return type; 
 
    }; 
 
    queue.dequeue = function() { 
 

 
     var type = list.shift(); 
 
     onDequeue(queue, type); 
 

 
     (list.length || onEmpty(queue)); 
 

 
     return type; 
 
    }; 
 
    Observable.call(queue); 
 
    //Allocable.call(queue, list); 
 
    }; 
 

 
    return Queue; 
 

 
}).call(null); 
 

 

 
var q = new Queue; 
 

 
q.addEventListener("enqueue", function (evt) {console.log("enqueue", evt);}); 
 
q.addEventListener("dequeue", function (evt) {console.log("dequeue", evt);}); 
 
q.addEventListener("empty", function (evt) {console.log("empty", evt);}); 
 

 
console.log("q.addEventListener : ", q.addEventListener); 
 
console.log("q.dispatchEvent : ", q.dispatchEvent); 
 

 
console.log("q.enqueue('the') ... ", q.enqueue('the'));  // "enqueue" Object {type: "enqueue", item: "the", target: Queue} 
 
console.log("q.enqueue('quick') ... ", q.enqueue('quick')); // "enqueue" Object {type: "enqueue", item: "quick", target: Queue} 
 
console.log("q.enqueue('brown') ... ", q.enqueue('brown')); // "enqueue" Object {type: "enqueue", item: "brown", target: Queue} 
 
console.log("q.enqueue('fox') ... ", q.enqueue('fox'));  // "enqueue" Object {type: "enqueue", item: "fox", target: Queue} 
 

 
console.log("q.dequeue() ... ", q.dequeue()); // "dequeue" Object {type: "dequeue", item: "the", target: Queue} 
 
console.log("q.dequeue() ... ", q.dequeue()); // "dequeue" Object {type: "dequeue", item: "quick", target: Queue} 
 
console.log("q.dequeue() ... ", q.dequeue()); // "dequeue" Object {type: "dequeue", item: "brown", target: Queue} 
 
console.log("q.dequeue() ... ", q.dequeue()); // "dequeue" Object {type: "dequeue", item: "fox", target: Queue} 
 
               // "empty" Object {target: Queue, type: "empty"} 
 
console.log("q.dequeue() ... ", q.dequeue()); // "dequeue" Object {type: "dequeue", item: undefined, target: Queue} 
 
               // "empty" Object {target: Queue, type: "empty"}
.as-console-wrapper { max-height: 100%!important; top: 0; }