ブレンドモード(Mixin)

4999 ワード

ブレンドモード(Mixin)
MixinはJavaScriptで使われている最も一般的なモデルで、ほとんどの流行ライブラリでMixinが実現されます.
Mixinは、混合、混合、混合という意味で、いずれかのオブジェクトの全部または一部の属性を他のオブジェクトにコピーすることができます.
提供したインターフェースから見ると、対象に対する操作もあれば、クラスに対する操作もあります.類に対する操作は混元類ともいいます.
 
一、添加対象(Mixin object)
まず一番簡単なmixinを見て実現します.
function mixin(dest, src) {
    for (var key in src) {
        dest[key] = src[key]
    }
}
使用します
var person = {name: 'John', age: 29}
var obj = {}
mixin(obj, person)
console.log(obj) // {name: 'John', age: 29}
personの属性はすべてObjにコピーされていることが分かる.一つの欠点があります.Objにもうname:'Jack'があったら、personに覆われます.したがって、dest上に既に存在しているなら、コピーしないという判断が必要です.
function mixin(dest, src) {
    for (var key in src) {
        if (!dest[key]) {
            dest[key] = src[key]
        }
    }
}
var person = {name: 'John', age: 29}
var obj = {name: 'Jack'}
mixin(obj, person)
console.log(obj) // Object { name="Jack", age=29}
もちろん、より強力で柔軟なMixinを提供することができます.例えば、任意の複数のオブジェクトをターゲットオブジェクトに組み込むことができます.
function mixin(dest, src) {
    for (var key in src) {
        if (!dest[key]) {
            dest[key] = src[key]
        }
    }
}
var person = {name: 'John', age: 29}
var obj = {name: 'Jack'}
mixin(obj, person)
console.log(obj) // Object { name="Jack", age=29}
以下の種類の倉庫はすべて対象に対する混ぜ合わせです.
  • jQueryの$exted オブジェクトを操作して、他のオブジェクトの属性方法を対象オブジェクトにコピーします.
  • RequireJSのプライベートmixinオブジェクトを操作して、他のオブジェクトの属性方法を対象オブジェクトにコピーします.
  • ExtJSのExt.appy 操作対象でもあります.defaultsパラメータも提供します.
  • Underscore.jsの _.extedは、第二のパラメータからのすべてのオブジェクトを第一のパラメータ
  • にコピーします.
     
    二、ミックス類(Mixinクラス)
    いくつかの翻訳は、ドーパントと呼ばれています.厳格な継承を必要としないでコードを多重化できる技術です.複数の種類がある種類の方法を使いたいなら、これらのタイプの原型を拡充して共有することができます.たとえば、まずさまざまな共通の方法を含むクラスを作成し、他のクラスを拡張します.これは一般的な方法を含む種類をドーパントといいます.多くの場合、直接的な実装や呼び出しではなく、他のクラスのテンプレートとして拡張されます.
    まず簡単な実現を見ます.
    //     ,  mixin
    function augment(destClass, srcClass) {
        var destProto = destClass.prototype
        var srcProto  = srcClass.prototype
        for (var method in srcProto) {
            if (!destProto[method]) {
                destProto[method] = srcProto[method]
            }
        }
    }
     
    function Person() {} //         ,  mixin
    Person.prototype.getName = function() {}
    Person.prototype.getAge  = function() {}
     
    function Student() {} //         
     
    augment(Student, Person) //   ,  
     
    var s1 = new Student()
    console.log(s1) // Student { getName=function(), getAge=function()}
    ツール関数augmentは2つのパラメータを受け入れます.いずれも関数タイプです.最初のクラスは2番目のクラスの原型からその方法を継承します.Personクラスを使ってStudentクラスを拡張しました.
    いくつかの言語はC++/Pythonのように、いくつかの親のクラスを継承することができますが、JavaScriptでは許可されていません.一つのコンストラクタは一つのプロトタイプのオブジェクトしかないです.しかし、これは複数のドーパント方式によって拡張されます.mixin方法と似ています.augment方法を修正してください.
    function augment(destClass, /*, Any number of classes */) {
        var classes = Array.prototype.slice.call(arguments, 1)
        for (var i=0; i<classes.length; i++) {
            var srcClass = classes[i]
            var srcProto  = srcClass.prototype
            var destProto = destClass.prototype     
            for (var method in srcProto) {
                if (!destProto[method]) {
                    destProto[method] = srcProto[method]
                }
            }       
        }
    }
    これで多継承が実現されました.
     
    すべての方法を継承したくない場合があります.指定された方法をコピーすることを指します.パラメータを一つ追加します.
    function augment(destClass, srcClass, methods) {
        var srcProto  = srcClass.prototype
        var destProto = destClass.prototype     
        for (var i=0; i<methods.length; i++) {
            var method = methods[i]
            if (!destProto[method]) {
                destProto[method] = srcProto[method]
            }
        }
    }
    function Person() {}
    Person.prototype.getName = function() {}
    Person.prototype.setName  = function() {}
    Person.prototype.getAge  = function() {}
    Person.prototype.setAge  = function() {}
     
    function Student() {}
     
    augment(Student, Person, ['getName', 'setName'])
    var s1 = new Student()
    console.log(s1) // Student { getName=function(), setName=function()}
    Backboneは多くの種類の添加物を使用しています.
    まず、Backboneライブラリ自体はMixin clases方式で組織されています.Backbone.Eventsは最下層の添加元類で、その方法はBackbone.Model/Backbone.clollect/Backbone.Viewなどに継承されています.コードのセグメントは以下の通りです
    _.extend(Model.prototype, Events, {
        ...
    })
    _.extend(Collection.prototype, Events, {
        ...
    })
    _.extend(View.prototype, Events, {
        ...
    })
    ここで_を使いますextedはModel,Collection,Viewの原型を拡充して,Eventsの方法を全部原型にコピーします.つまりEventは一つのドーパント(一つの対象として実現されますが)です.
     
    次に、私達がBackboneを使って開発する時、あなたが書いたモデルはBackbone.Modelで拡張します.ビューはBackbone.Viewで拡張します.如き
    var MyModel = Backbone.Model.extend({
        instanceProp: xx
    },{
        classProp: yy
    })
     
    var MyView = Backbone.Model.extend({
        instanceProp: xx
    },{
        classProp: yy
    })
    この時、Backbone.Model/Backbone.Viewなどは元を混ぜました.もちろん、アンダースコアをドーパントの対象としてもいいです.Backboneの多くの種類が引き継ぎました.exted方法は、Backbone.Events/Backbone.Modelなどです.
    原文の出所:http://www.cnblogs.com/snandy/archive/2013/05/24/3086663.html