1.不純物は、実際、何ですか?
混合物(mixin)は、一連の機能を持つオブジェクトであり、それ自体は(他のオブジェクトとは別に)使用されません。
たとえば、ここに素晴らしい混合物があります:
var Mixin_Babbler = { say: function () { console.log("My name is " + this.name + " and i think:'" + this.THOUGHTS + "'"); }, argue: function() { console.log("You're totally wrong"); } };
このようにsayメソッドを呼び出そうとすると、なんらかの理由でオブジェクトのthis.nameもthis.THOUGHTSも存在しないため、 残念なことに待っています。
実際、意図した目的に不純物を使用するには、すべてが正しいため、別のオブジェクトと、転送された不純物オブジェクトのすべてのプロパティをコンストラクター関数のプロトタイプにコピーするメソッドが必要です-通常、このメソッドは、extend、mix、またはそのようなものと呼ばれます:
function extend(object) { var mixins = Array.prototype.slice.call(arguments, 1); for (var i = 0; i < mixins.length; ++i) { for (var prop in mixins[i]) { if (typeof object.prototype[prop] === "undefined") { object.prototype[prop] = mixins[i][prop]; } } } }
2.さて、それを使用するには?
簡単で負担なし-不純物がいくつかあるとしましょう:
var Mixin_Babbler = { say: function () { console.log("My name is " + this.name + " and i think:'" + this.THOUGHTS + "'"); }, argue: function() { console.log("You're totally wrong"); } }; var Mixin_BeverageLover = { drink: function () { console.log("* drinking " + this.FAVORITE_BEVERAGE + " *"); } };
そして、おそらく既におなじみの誰かに、進化の連鎖:
function Man(name) { this.name = name; } Man.prototype = { constructor: Man, THOUGHTS: "I like soccer" } extend(Man, Mixin_Babbler); function Gentleman(name) { this.name = name; } Gentleman.prototype = { constructor: Gentleman, THOUGHTS: "I like Earl Grey", FAVORITE_BEVERAGE: "Tea" } extend(Gentleman, Mixin_Babbler, Mixin_BeverageLover); function Programmer(name) { this.name = name; } Programmer.prototype = { constructor: Programmer, THOUGHTS: "MVC, MVVM, MVP *___* like it!", FAVORITE_BEVERAGE: "Cofee", write_good_code: function () { console.log("*writing best code ever*"); this.drink(); } } extend(Programmer, Mixin_Babbler, Mixin_BeverageLover);
各「クラス」は互いに独立しており、すべての繰り返し機能は不純物を使用して実装されています。
今ではすべてをチェックする価値があります-突然動作します:
var man = new Man("Bob"); var gentleman = new Gentleman("Bill"); var programmer = new Programmer("Benjamin"); man.say(); man.argue(); gentleman.say(); gentleman.drink(); programmer.say(); programmer.write_good_code();
コンソールには「はい」と表示されます。
My name is Bob and i think:'I like soccer' *You're totally wrong* My name is Bill and i think:'I like Earl Grey' *drinking Tea* My name is Benjamin and i think:'MVC, MVVM, MVP like *__* it!' *writing best code ever* *drinking Cofee*
実際にはすべて。 「古典的な」継承とは異なり、不純物の実装は非常に単純で簡単です。 もちろん、いくつかのバリエーションがありますが、いずれにしても、カーネルはまったく同じように見えます。
UPD。 lalakiというニックネームを持つ非常に良い人が提案したように、extendメソッドは少し異なる方法で実装できます。
function extend_2(object) { var mixins = Array.prototype.slice.call(arguments, 1); for (var i = 0; i < mixins.length; ++i) { for (var prop in mixins[i]) { if (typeof object.prototype[prop] === "undefined") { bindMethod = function (mixin, prop) { return function () { mixin[prop].apply(this, arguments) } } object.prototype[prop] = bindMethod(mixins[i], prop); } } } }
このアプローチを使用すると、メソッドをその場で不純物に置き換えることができ、これらの変更はこの混合物を使用するすべてのオブジェクトですぐに利用できます。
非常に小さな欠点は、開発環境のあまり賢くないヒントが、メソッドに引数がないことを常に示すことです。
すべてのコードと例はここに落ち着いてあります。