pirosikick's diary

君のハートにunshift

YUIの継承系メソッド

初ブログ。大したこと無いことを書きます。

YUIいいね!

アーティストのYUIではなく、Yahoo UI Libraryの方です。ドキュメントやらソースやら見ていてこれおもしろいなーと思ったので最近はまってます。

ソース読んでるとよく出てくるメソッド

んで、ソース読んでると継承系の下記4つのメソッドが本当によく出てくる。

  • mix
  • extend
  • aggregate
  • augment

なんとなくしかわかってなかったので、調べました。

mix

Baseモジュールにもstaticメソッドでmixがあるが、これはYUIクラスにあるmixメソッド。特にモジュールを呼び出さずに使用可能。

mix ( receiver, supplier, [overwrite=false], [whitelist], [mode=0], [merge=false] ) 
引数 説明
reciever Object or Function mixされるObject or Function
supplier Object or Function recieverにmixするObject or Function
overwrite bool trueの場合、recieverに既に同じ名前のプロパティがあった場合に上書きする
whitelist 文字列のArray whitelistが定義されている場合、その中にある名前のプロパティのみコピーされる
mode 0 ~ 4 動作モード
merge bool コピー時にコピー先と元が両方共、ArrayもしくはObjectの場合に、結合する。mergeとoverwriteがどちらもtrueの場合は、mergeが優先される

modeの値によって動作が変わります。

mode 動作
0 supplierのプロパティをrecieverにコピー
1 supplier.prototypeのプロパティをreciever.prototypeにコピー
2 modeの0と1の両方
3 supplier.prototypeをrecieverにコピー
4 supplierをrecieverにコピー
サンプル
// 普段はこういう使い方はしない
var Y = YUI();

// reciever
function r () {}

// supplier
function s () {}
s.a = "hogehoge";
s.b = "hogehoge";

// modeのデフォルトは0
Y.mix(r, s);
r.a; // "hogehoge"
r.b; // "hogehoge"

extend

oopモジュールのextendメソッド。

extend ( r, s, [px], [sx] ) 
引数 説明
r Function 継承する(?)Function
s Function rが継承するFunction
px Object r.prototypeに追加・上書きするObject
sx Object rに追加・上書きするObject

ソースを見て要約すると下記の動作

function F () {};

F.prototype = s.prototype;

r.prototype = new F();
r.prototype.constructor = r;
r.superclass = s;

for ( var k in px ) {
    r.prototype[k] = px[k];
}

for ( var k in sx ) {
    r[k] = sx[k];
}

aggregate

oopモジュールのaggregateメソッド

aggregate ( r, s, ov, wl ) 

関数内でY.mixを下記のように呼んでいるだけ。

return Y.mix(r, s, ov, wl, 0, true);

ドキュメントにはコピー先がArrayの場合はsの値がその配列に追加するって書いてあるけどうまくいかない。。ソース見る感じ、そういう仕様ではないと思う、たぶん。勘違いかなー。

サンプル
YUI().use("oop", function (Y) {

// reciever
var r = {
    a: {a:"aaa"}
};

// supplier
var s = {
    a: {b:"bbb"},
    b: "hoge"
};

Y.aggregate(r, s);

r.a; // {a:"aaaaa", b:"bbbbb"}
r.b; // "hoge"

});

augment

oopモジュールのaugmentメソッド

augment ( receiver, supplier, [overwrite=false], [whitelist], [args] )
引数 説明
receiver Object or Function コピー先のオブジェクト
supplier 必ずFunction コピー元のFunction
overwrite bool Y.mixとかと同じ
whitelist array Y.mixとかと同じ
args array sのコンストラクタ実行時に渡す引数

動作

receiverがObjectかFunctionかで動作が違います。

receiverがObjectの場合は、supplier.prototypeをreceiverにコピーし、supplierのコンストラクタ関数をreceiverがthisになるように実行する。

// こんな感じ
Y.mix(receiver, supplier.prototype, overwrite, whitelist);

supplier.apply(receiver, args);

receiverがFunctionの場合は、receiver.prototypeにsupplier.prototypeをコピーし、実際はちょっと違うけど、recieverのインスタンスが生成されるときにsupplierのコンストラクタも実行されるように細工する。(本当の実装はもっと複雑で、supplierのコンストラクタ実行を本当に必要なタイミングまで行わないようにし、パフォーマンスを良くしようとしている)

サンプル
YUI().use("oop", function (Y) {

var r = {a: "aaaa"};

var s = function (c) {
    alert("execute S!!");
    this.c = c;
};
s.prototype.b = "bbbb";

Y.augment(r, s, false, null, ["cccc"]); // "execute S!!"でアラート発生

r.b; // "bbbb"
r.c; //  "cccc"

});

まとめ

なんとなく理解しているつもりだったけど調べてみるとより理解が深まったような気がします。ここ1年くらいものを作りたいという気持ちが強くあるのにモノができないっていうスランプ状態に陥っているけど、興味があることは調べて発信していければなと思います。ほなまた!