記事の目的
本記事の目的はjQueryのコードが理解できるようになることです。動きのあるwebページを作成する際、ネットではjQueryの記事がよく出てきますが、javascriptは分かっても、jQueryがわからないと困ります。この記事では、jQueryを解読する際に必要な予備知識を解説します。
必要知識
html, css, javascriptの基礎知識
jQueryとは
jQueryとは、javascriptのライブラリのことです。
ライブラリというと、関数や変数が定義されているものですがjQueryには、何が定義されているのでしょうか。それは、“jQueryオブジェクト”です。
つまり、jQueryのライブラリファイルを読み込めば、通常のjavascriptの関数に加えて、jQueryオブジェクトの関数が使用できるようになります。
jQueryオブジェクトには‘jQuery’でアクセスできますが、記述を簡単にするために、‘$’で置き換えることができるようになっています。
以下は、jQueryオブジェクトに登録されているtrim関数を呼び出した例です。
1 2 3 4 5 6 7 |
// 文字列の前後の空白を取り除いてコンソールに表示 var trimed = jQuery.trim(' abc '); console.log(trimed); // 出力 'abc' // 以下のように$で記述しても同様 var trimed = $.trim(' abc '); console.log(trimed); // 出力 'abc' |
$ = jQueryと認識していてください。この記事で出てくるコードの$もすべてjQueryという表記に置き換え可能です。
$を見かけたら、とにかく、「jQueryの関数を使いたいのだな」と解釈してください。以下、$の主要な使われ方を紹介します。
$(…)
$(…)という記述がjQueryのコードでは必ず見かけられます。これは関数を表しているのですが、用途が多岐にわたるので、予備知識なしで見ると理解に苦しみます。ここでは、$()関数の主な使い方を3つ解説します。
- 引数に文字列をとる場合:$(‘…’)
- 引数にElementをとる場合:$(…)
- 引数に関数をとる場合:$(function(){})
これらは、すべて公式ドキュメントに記載されているので、詳しくは
https://api.jquery.com/jQuery/#jQuery-element
をご参照ください。
1. 引数に文字列をとる場合:$(‘…’) ⇒ セレクタ
html上の要素を取得したいときに使用し、この使い方のことをセレクタと呼びます。例えば、$(‘div’) と記述することで、htmlのdiv要素を取得できます。javascriptの document.getElementsByTagName(‘div’) に対応しますが、以下のように返り値が異なります。
- $(selector):jQueryオブジェクト
- getElementByTagName(tagName):HTMLCollection
$(selector) の返り値は、jQueryオブジェクトと呼ばれるものになっており、jQueryで定義された様々な関数を使用できます。以下では、.css() 関数を呼び出しています。
1 2 |
// div要素のleftを400pxに変更 $('div').css('left', '400px'); |
$(…)の … はcssのセレクタとほぼ同じ方法で指定でき、
- $(‘.boxA’):class=”boxA” の要素を取得
- $(‘#table-first’):id=”table-first” の要素を取得
となります。それぞれ、document.getElementsByClassName や document.getElementById に対応します(もちろん返り値は異なり、$() はjQueryオブジェクト、getElement系はHTMLCollectionやElementを返します)。その他、セレクタの記述方法については、
http://www.hp-stylelink.com/news/2013/11/20131122.php
をご参照ください。
2. 引数にElementをとる場合:$(…) ⇒ jQuery変換
以下のように、getElementById()などで取得したElementを、jQueryの関数が使えるようにjQueryオブジェクトに変換する時に使用することもあります。
1 2 3 |
var elem = document.getElementById('something'); var $elem = $(elem); // ※変数名には'$'を接頭辞としてつける習慣があります。 $elem.height('300px'); |
.height()は、jQueryで定義された関数で、要素の高さを引数で指定した高さに設定します。これは、jQueryオブジェクトではないと使用できないので、$(elem)によって変換する必要があったのです。
実際には、この使い方はイベントハンドラー内のthisでよく見られます。
1 2 3 4 5 6 |
// class="boxA"がクリックされたらその高さを300pxに変更 $('.boxA').on('click', function(){ // thisは.boxAを表すElementオブジェクト。$(this)でjQueryオブジェクトに変換している。 $(this).height('300px'); }) |
thisはその文脈によって参照するオブジェクトが変わりますが、気になる方はhttps://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Operators/this
をご覧ください。
$()の引数にElementが指定されていたら、「この後でjQueryの関数使いたいんだな」と解釈すれば良いと思います。
3. 引数に関数をとる場合:$(function(){…}) ⇒ readyイベント
引数に関数を指定すると、$(document).ready()と同じ意味になります。
readyイベントはHTMLのDOMツリーの読み込み完了時のイベントで、jQueryを使わない場合のDOMContentLoadedイベントと対応します。
以下のように使います。
1 2 3 4 5 6 7 8 9 |
// ページ読込が完了したら、'hello'と表示 $(function(){ console.log('hello'); }) // 同じ意味 $(document).ready(function(){ console.log('hello'); }) |
多くのjQueryのサンプルコードで見かけるので、これを見かけたら、「最初に実行したい処理が書かれているんだな」くらいに思っていただければ良いと思います。
$
$の関数としての使い方については前述しましたが、$単体で以下のように使用することも可能です。
1 2 |
// 数値かどうか判定 ⇒ "true" console.log($.isNumeric( "0" )); |
$の後に(…)と引数を記述する部分がない場合、$は関数ではなく、関数をその要素として持つオブジェクトとして解釈できます。jQueryに慣れるまでは、$(…)と$が入り乱れていると、$が関数なのかオブジェクトなのか混乱しますが、両方の使い方があると知っていれば問題ありません。というより、javascriptでは関数もFunctionオブジェクトというオブジェクトです。JavaやC#を初めに学んだ方にとっては衝撃ですが。
$には他にも様々な関数が定義されており、
https://api.jquery.com/category/utilities/
で確認可能です。
実際のコードの解読
ここまで、$の使い方を説明してきましたので、後はjQueryに定義されている関数を都度調べれば、コードの解読、記述が可能です。
実際にプラグインとしてMITライセンスで配布されているshuffleLettersのコードを読み解いて行きましょう。
https://tutorialzine.com/2011/09/shuffle-letters-effect-jquery
以下、実装になります。説明はコメントアウトの部分に書いてあります。なお、コードの理解には、即時実行関数の知識が必要です。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 |
/* ============================================ * * プラグインの部分 * * ============================================*/ // プラグインは必ず(function($){内容})(jQuery)という // 即時実行関数の形になっています。 (function($) { // $.fnにshuffleLetters関数を定義。 // fnに登録された関数はjQueryオブジェクトから呼び出せるようになる。 $.fn.shuffleLetters = function(prop){ // $.extendでjQueryにプロパティを追加 var options = $.extend({ "step" : 8, // 文字が何回変更されるか "fps" : 25, // 1秒あたりのフレーム数 "text" : "" // 内容の代わりにこのtextを使用 },prop) // ここから本題。 // thisは配列ライクの構造で、DOM要素が格納されている。 // ⇒[element1, element2, element3] // each()でそのDOM要素それぞれに処理を実行。 return this.each(function(){ // thisはDOM要素。 // $(this)でjQueryオブジェクトに変換し、elに格納。 var el = $(this), str = ""; // シャッフルしたい文字列を一文字区切りで配列にし、strに格納 if(options.text) { str = options.text.split(''); } else { str = el.text().split(''); } // types配列はそれぞれの文字の種類 // (大文字、小文字、記号、スペース)を格納 // letters配列はスペース以外の文字についてその位置を格納 var types = [], letters = []; // 文字列一つ一つについてループし、 // types配列とletters配列を作成 for(var i=0;i<str.length;i++){ var ch = str[i]; if(ch == " "){ types[i] = "space"; continue; } else if(/[a-z]/.test(ch)){ types[i] = "lowerLetter"; } else if(/[A-Z]/.test(ch)){ types[i] = "upperLetter"; } else { types[i] = "symbol"; } letters.push(i); } // 表示文字列をいったんクリア el.html(""); // 関数shuffleの定義 (function shuffle(start){ // この部分は1秒あたりoptions.fpsで指定された回数実行され、 // ページ要素の表示文字列を変更。 var i, len = letters.length, strCopy = str.slice(0); // 文字列をコピー // シャッフルの終了条件 if(start>len){ return; } // シャッフルの部分 for(i=Math.max(start,0); i < len; i++){ // 対象範囲内の場合 if( i < start+options.step){ // この位置でのランダム文字を生成 strCopy[letters[i]] = randomChar(types[letters[i]]); } // それ以外の場合は表示しない。 else { strCopy[letters[i]] = ""; } } // 生成した文字列で画面のtextを表示変更 el.text(strCopy.join("")); // setTimeoutは指定した時間後にfunction(){}内を実行。 // ここでは、1000/options.fps (ms)後に // shuffle()をstart位置を1つ上げて実行する指示。 setTimeout(function(){ // 自分自身をstart+1で実行 shuffle(start+1); },1000/options.fps); })(-options.step); // ↑ ()内で定義した関数shuffleを // (-options.step)を引数にして実行 }); }; // ランダム文字生成関数の内部実装は省略 function randomChar(type){ // Generate and return a random character } })(jQuery); /* ============================================ * * ユーザが書く部分 * * ============================================*/ // readyイベントでの処理 $(function() { // containerはDOM要素。クリックでシャッフル。 $("#container").on('click', function() { // containerの中身をシャッフル // $.fnにshuffleLettersを登録したので、使用可能 // (thisはイベント登録した#container要素を表す) $(this).shuffleLetters(); }); }); |
即時実行関数
javascriptでは即時実行関数というものがあります。上記のshuffleLettersでも2箇所使用されています。以下の形になっていれば、即時実行関数です。
1 2 3 |
(function(仮引数) { … })(実引数) |
() 内で関数を定義し、それをすぐに (実引数) で実行します。
以下に、関数の使用を即時実行関数に書き換える例を示します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
/* ============================================ * * 関数定義部分と実行部分を分ける場合 * * ============================================*/ function selfIntroduce(name) { console.log('私の名前は' + name + 'です。'); } // 出力:私の名前は太郎です。 selfIntroduce('太郎'); /* ============================================ * * 即時実行する場合 * * ============================================*/ // 出力:私の名前は太郎です。 (function(name) { console.log('私の名前は' + name + 'です。'); })('太郎') |
他の箇所で再利用しない関数の場合、このように即時実行関数の書き方をすることで記述量を減らすことができます。
jQueryのプラグインが即時実行関数の形になっているのは、
- プラグインのjQueryへの登録処理は再利用しないため
- $の競合を防ぐため
の二つあります。$の競合については、
https://uxmilk.jp/29304
をご覧ください。
まとめ
ここまで解説した通り、jQueryのプログラムはjavascriptにjQueryオブジェクト (= $) が追加されただけのものです。 $の使い方さえ理解していれば簡単なので、あまり身構えず、積極的に使用していただければと思います。