Edited at

正しく、効率が良いjQueryライブラリの書き方を学ぶ

More than 1 year has passed since last update.

何となく書いてごまかしてきたJavaScriptやjQueryを、このところきちんと勉強しています。

オプション豊富なスライドショーを作成できる「Slick」のコードを参考に、メソッドなどを読み込んでみました。

https://github.com/kenwheeler/slick/

他のスクリプトと衝突しない、オブジェクト指向のjQueryライブラリの書き方をだいたい理解したので、おさらいとしてまとめてみます。


2016-12-27 追記

コメント欄でいただいたアドバイスをもとにひな型を改良しました。

https://codepen.io/webbingstudio/pen/JbQjzw


2016-12-02 追記

ここのコメント欄とSNSなどで以下のようなアドバイスをいただきましたm(__)m


  • jQueryっぽく書くのなら38行目のcss()はwidth()、48行目のmatch()はhasClass()が良いのでは

  • このコードの場合、9行目のsample.prototype.initではなく、4行目のwindows.sampleがコンストラクタにあたる

  • 変数にアンダースコアを使うのは一般的ではない。Underscore.jsと衝突する可能性もある


サンプルコード

CodePenに置いたこちらのライブラリを前提に解説します。

指定した包括要素内にある、任意のクラスが付与された要素(ここではボタン)をクリックすると、いろいろな演出が発動します。

包括要素は何個あっても、それぞれ個々に稼働します。

jQueryライブラリのひな形(仮)

https://codepen.io/webbingstudio/pen/RoLaQp


全体の構造

ライブラリの最初と最後は以下のようにします。「この範囲内では、\$はjQueryを表す」と明示をしています。jQueryはいきなり\$を書いても動作しますが、本来はきちんと宣言すべきです。

;(function($){

"use strict";

...

})(jQuery);

最初のセミコロンは、正直まだよくわかりません。おそらく、これの前のメソッドが不完全であっても、一旦終了させることでエラーを出さずに起動できるのかな…と推測しています。

!になっているライブラリもあるようです。

"use strict"; は「厳格モード」で起動するという意味です。

曖昧な表現ができなくなり、例えば変数を宣言するときにthis・var・windowなどを明示していないとエラーになります。


sampleオブジェクト

4〜75行目は「指定した要素に、具体的に何をさせるか」を定義している部分です。要素が何個あっても複製して使い回せるお得なパッケージです。これは、PHPだと「クラス」と呼ばれているものです。

オブジェクト名は「sample」にしています。Slickだと「Slick」となっています。

window.sample = function(e, options) {

// 最初に必ず行う処理(コンストラクタといいます)
var
_ = this,
s;

sample.prototype.init = function() {
// 最初に必ず起動する関数
};

sample.prototype.read = function(o) {
// クリックした要素の属性をアラートする処理
};

sample.prototype.wide = function(o) {
// クリックした要素の幅を広げる処理
};

sample.prototype.expand = function(o,t) {
// 隠れている文字を展開する処理
};

// initを起動
// 各関数の起動条件を指示(クリックしたときなど)

};

通常、jQueryを通してオブジェクトを実行すると「this」に指定した要素が入ります。しかし、thisをそのまま使用すると、jQueryのeachやonを使ったときに曖昧になってしまうので、一意の名前の変数に移します。Slickの場合「_」一文字を変数にしています。

    var

_ = this,

なので、init関数を起動するときは以下のようになります。

_.init();


prototypeとは

ネットで色々調べると、各関数を以下のように書いているケースも見られます。

this.init = function() {

間違いではないのですが、この書き方だと要素の数だけ「init」が作られることになり、要素が100個とかになるとまずいことになります。

「prototype」は、JavaScriptのオブジェクトに最初からセットされている変数です。ここに関数を入れておくと、要素が何個あっても共通の「init」を参照するようになるのです。


$.extendとは

9〜12行目は最初にオブジェクトを実行したときに必ず行う処理です。

「$.extend」というのはjQueryのメソッドで、「前もって指定しておいた規定値を、指定された値で上書きする」というものです。ここだとinitialsをoptionsが上書きします。

optionsはどこにあるのかというと、93行目にあります。後述します。


$.fnとは

77行目〜91行目は、jQueryの処理です。$.fnは、指定した要素(this)に対してfunction内の処理を実行します。やっていることをざっくり書くと以下の通りです。

$.fn.sample = function() {

// 指定された要素が何個あるか調べる
// sampleオブジェクトを作って結びつけることを、要素の数だけ繰り返す
// 引数があり、かつ、正しい書式になっていれば、オプションとしてオブジェクトに渡す
};

この辺は決め打ちでいいようです。sampleを自分が作ったオブジェクト名に変えるだけです。

実はSlickでは、このときに内部関数を直接実行できるような判定もしているのですが、よくわからなかったのでカットしました。


実行する

$.extendのところで触れた93行目です。そう、デザイナーがいつも書いてるライブラリの実行部分です。

$(function(){

$('.js-sample').sample({
read: '.sample-read',
wide: '.sample-wide',
expand: '.sample-expand',
expand_target: '.sample-expand-target',
show_speed: 1000,
hide_speed: 500
});

});

もしも以下のようにオブジェクト名だけで実行した場合は、オプションがないので、10行目のinitialsを元に実行されることになります。今回のサンプルコードの場合、クラス名が違ってしまうので、HTMLを修正しないと動きません。

$(function(){

$('.js-sample').sample();

});

以下のようにスピードだけ指定した場合は、表示される早さだけが上書きされます。

$(function(){

$('.js-sample').sample({
show_speed: 1000,
hide_speed: 500
});

});


まとめ:実行順

全体の実行順は以下の通りになります。


  1. 93〜104行目

  2. 77行目〜91行目

  3. 9〜12行目

24〜30行目・32〜42行目・44〜58行目は、クリックなどの指定したイベントが発生するまでは実行されません。


以上です。

さささ参考になれば幸いです…((((;゚Д゚))))))