extendといえば、"継承する"という意味だと思っておりましたが、広げる、拡張するといった意味合いの言葉のようです。
jQueryプラグインを作成する際にも使用し、意味合い的にもぴったりのextendですが、それ専用のメソッドというわけではありません。
公式のドキュメントはプラグイン作成用途ではない説明がメインで行われているため、まずはこの使い方を理解する必要があるでしょう。
jQuery.merge
jQuery.merge( Array1, Array2 )
マージといえば、割とおなじみの言葉だと思います。なんか混ぜ合わせる感じですが、jQueryのextendとmergeはほぼ同じものといっていいと思います。違うのは、混ぜ合わせるのが配列かオブジェクトかという点です。
jQuery.mergeの特徴
- 配列(Array)をマージする
- 引数はn個ではない
- 何個でもマージできるわけではなく2個
- Array1が上書きされる
Array1が上書きされたくないときの書き方
var first = [ "a", "b", "c" ];
var second = [ "d", "e", "f" ];
var mg_arr = $.merge( $.merge( [], first ), second );
空の配列にマージしてます。$.mergeの返り値はマージ後の配列なのでそれを変数に代入しています。
通常Array1が書き換わるため、空の配列ではない場合、マージ時の返り値を変数に代入する必要はありません。
var first = [ "a", "b", "c" ];
var second = [ "d", "e", "f" ];
$.merge( first , second );
first; // 書き換わってる
jQuery.extend
// version 1.0~
jQuery.extend( target [, object1 ] [, objectN ] )
// version 1.1.4~
jQuery.extend( [deep ], target, object1 [, objectN ] )
2種類の書き方があるんです。すでにややこしいですが、mergeと対比するextendはversion 1.1.4の書き方です。
ほぼ一緒のように見えますが、version 1.0はオブジェクトが一つでもいいところが大きな違いです。
以降は、version 1.1.4から追加されたほうのextendに関する解説です。
jQuery.extendの特徴
- オブジェクトをマージする
- 引数はn個(何個でも!)
- Array1が上書きされる
Array1が上書きされたくないときの書き方
var object = $.extend({}, object1, object2);
mergeと大体同じですが、引数がn個なおかげで、すっきり書くことができます。
[deep ]オプション
このオプションは、true
を指定するか、もしくは省略するかのどちらかです。false
を指定することはできません。
説明によると、
If true, the merge becomes recursive (aka. deep copy).
ということです。trueだったら、マージが再帰的になる
なるほど、わからんですね。
サンプルを見てみましょう。
var object1 = {
apple: 0,
banana: { weight: 52, price: 100 },
cherry: 97
};
var object2 = {
banana: {
price: 200
},
durian: 100
};
$.extend( object1, object2 );
結果は以下のようになりました。
$.extend( object1, object2 );
Object {
apple : 0
banana : Object {
price : 200
}
price : 200
cherry : 97
durian : 100
}
weightがなくなってしまいました。
[deep ]をtrueにすると結果は、以下のように変わります。
$.extend( true, object1, object2 );
Object {
apple : 0
banana : Object {
weight : 52,
price : 200
}
price : 200
cherry : 97
durian : 100
}
今度は、weightが残ったままのようです。
aka. deep copy
という説明がありましたが、深い階層も同じように処理するかどうかということです。
trueにすると、オブジェクトの中のオブジェクトも同じようにマージしてくれます。trueでない場合は、中身を無視してまるごと上書きしてしまった感じです。
jQueryプラグインのためのextend
jQuery.fn.extend( object )
上記とjQuery.extend
は似ていますが、fn
をつけるだけで全く異なるものになることに注意してください。
jQueryは、fn
をつけることによって、prototypeを参照します。(prototypeが何なのか気になる場合は、こちらを参考にしてみてください)
jQuery.fn.extend
について、$.each
を例にご説明します。
$.extend({
each : function() {}
});
// => $.each();
jQueryそのものをパワーアップさせるのが、$.extend
です。
ユーティリティ関数と呼ばれています。
<div class="btn"></div>
<div class="btn"></div>
<div class="btn"></div>
$.fn.extend({
each : function() {}
});
// => $(".btn").each();
jQueryでお馴染みの書き方ができるようになるのが$.fn.extend
です。JavaScript的にも頭にtargetがくる書き方はしっくりきます。
他にも以下のように書くこともできます。
$.fn.each = function() {}
});
$.extend($.fn, {
each : function() {}
});
これらはすべて、jQueryのprototypeを拡張する方法です。
each
は元々jQueryに存在するメソッドですが、オリジナルのメソッドを定義することもできます。
$.fn.extend({
open : function() {},
close : function() {}
});
一般的なjQueryプラグインもこのように拡張されています。
jQueryプラグインで便利なextendの使い方
jQueryプラグインで、ユーザーが自由に設定を変更できるオプションを作成する方法を紹介します。
jQueryプラグインには、初期値としてあらかじめdefaults
というオブジェクトを定義します。
var defaults = {
width: 100,
height: 100.
maxlength: 10,
message : {
ok : "good",
ng : "sorry"
}
}
このdefaults
に定義するのは、プラグインの中で使用する変数です。
$("#sample").hogePlugin({
width: 200,
message : {
ng : "bad"
}
});
このようにユーザーは、オプションを指定し、defaults
の値を更新することができます。実行時の引数に渡すというやり方がスマートです。
更にこのオプションのいいところは、指定したものだけを上書き、指定しなかったものは、defaults
の値を使用するところです。
これにより、「デフォルト値の場合は省略可」を実現できます。
もちろんこの際、オプションの値でdefaults
を更新するのに使用するのがextendです。
ダメな書き方
$.extend(defaults, options);
なぜダメかわかるでしょうか。
上でも説明しましたが、この例のようなオブジェクトの場合、"再帰的"にしなければmessage.okが消えてしまいます。
ただし、再帰的にする必要がなければ特に問題はありません。
普通な書き方
$.extend(true, defaults, options);
これで再帰的に処理されます。
しかし、個人的にはこれもまだ微妙です。これでは今後使用するのがdefaults
ということになります。defaults
はあくまで初期値であり、設定時に使用するのはoptions
を使用した方が綺麗でしょう。
マシな書き方
options = $.extend(true, defaults, options);
これでoptions
を使用できるようになりましたが、まだdefaults
が書き換わってしまっている点が微妙です。初期値が必要になった場合など困ってしまいます。
オススメの書き方
options = $.extend(true, {}, defaults, options);
これでdefaults
を保持しつつ、見事defaults
とoptions
をマージすることができました。