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年くらいものを作りたいという気持ちが強くあるのにモノができないっていうスランプ状態に陥っているけど、興味があることは調べて発信していければなと思います。ほなまた!