2012-11-29 19 views
5

私は小規模なエンタープライズアプリケーションを構築していますが、できるだけDRYしたいと考えています。その結果、私はmixinライブラリを見てきました。Javascriptでmixinsを正しく使用する方法

私はこのlibraryに出くわし、実行時に混在することができるので、良い選択肢かもしれないと考えました。また、私はちょうど1つの基本クラス(BaseView)を持つことができ、ちょうどそれのミックスイン。

質問

  1. 便利なミックスインのいくつかの実際の応用例は何ですか? (これ以上の抽象的な例はありません)
  2. クラスを拡張する必要がありますか、またはこのライブラリを使用してすべての拡張機能やミックスインを管理できますか?

答えて

2

mixinは、コードと継承を整理する方法とはまったく異なる概念です。もちろん、古典またはプロトタイプの継承を使用して組み合わせることもできますが、それはまた、スタンドアロンとしても機能します。例えば

、オブジェクトプロパティ/検索(のような原型継承)を「委任」の代わりにを作成するので、私たちは「フォーム」複数の他のオブジェクトから新しいスタンドアロンオブジェクト、本当にだろう。これは「複数継承」とも呼ばれ、Javascripts プロトタイプ継承だけでは簡単に達成できません。一例として、

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 
} 

私は実際にあなたの質問に正しく答えなかったが、あなたの質問に本当の答えがないように感じた。あなたが使っているのと同じくらいリアルですが、実際にはアプリケーション固有のユースケースはありません。

1

私たちはCocktailと呼ばれるmixinライブラリを使用しています(mixins ... get it?)。具体的には、Backboneアプリケーションでの使用ですが、かなり良いです。

written up details on our usage patterns私はここで説明するよりも優れた仕事をしています。

3

も参照してください。

ミックスインと特性のようなJavaScriptとロールベースの合成アプローチについては、私は非常に意見があります。私はいつも、2つの純粋に機能に基づいたパターンのライブラリーにとらわれないミックスを指し示します - まず第1にモジュールパターン、第2に、2011年5月にAngus Crollによって再発見、命名、記述された "Flight Mixin"パターンです。 4月2014

質問

    から鉱山の紙
  • 1)有用なミックスインの実際の応用例は何ですか? (これ以上の抽象的な例はありません)
  • 2)私はクラスを拡張する必要がありますか、またはこのライブラリを使用してすべての拡張機能やミックスインを管理できますか?
  • あなたの2つの質問に答える

...

第一

[Observable]はおそらくミックスインのための最も一般的な現実世界の例の一つです。しかし、これはコードベース全体を提供するための適切な場所ではありません。 Smart Talents chapterからの漸進的に成長する例は、最初に異なるMixins[Enumerable]および[Allocable]のように使用するが、最後に既に述べた[Observable]を適用する[Queue]の工場の実装形態を提供する。

2nd)ご希望のモジュールシステムをご利用いただくか、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; }

関連する問題