2012-11-29 51 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; }