デザイナーにも分かりやすいjQuery入門講座|jQueryの使い方

このエントリーをはてなブックマークに追加
索引
1章:jQuery入門
2章:jQuery基礎
3章:jQuery発展
番外編:研究

jQueryの高速化

概要

高負荷な処理を避ける

複雑なhtml構成のコンテンツや、複雑な計算が必要なコンテンツで無ければjQueryの動作速度が気になることはないと思います。しかし負荷が軽いに超したことはないので、負荷の軽いスクリプトを学んでおきます(負荷が高いとアニメがカクつく等の原因になります)。

jQueryの高速化
・jQueryオブジェクトの作成には負荷がかかる。
・セレクタは可能な限りclass属性よりも、id属性を利用する。
・何度も利用するjQueryオブジェクトは変数に入れて利用する。

解説

jQueryオブジェクトの作成には負荷がかかります

jQueryオブジェクトは作成の際に負荷が掛かります。これはセレクタで指定された要素をhtml内から探さないといけないためです。規模の大きいコンテンツでは多くのjQueryオブジェクトを利用するため、なるべく負荷をかけない工夫が必要になります(規模が小さければ余り気にしなくてもOKだと思います)。

セレクタにはclassよりもidを

ページ内に複数の設定をする場合は仕方ありませんが、ページ内に1つしかない場合はclass属性よりもid属性を利用しましょう。id属性の場合は、最初の1つを見つけたら以降のチェックはしないため負荷が軽いのです(class属性の場合は複数ある可能性があるのでページの最後までチェックします)。

セレクタの違いによって、どれくらい差が出るかを確認するサンプルを用意しました。
サンプル(speed/01.html)のソースを開いてbody内にbutton要素とdiv要素が2つあることを確認して下さい。id属性がtimeAreaのdiv要素には計測タイムを表示し、class属性がtestAreaのdiv要素には処理内容を表示します。着目しておくのは処理内容を表示するdiv要素に「class属性」が設定されていることです。

<button>start</button>
<div id="timeArea"></div>
<div class="testArea"></div>

jQueryは以下の様に記述され、3〜5行目のfor文で「class属性」がtestAreaの要素に0〜1000の数字を表示していきます。それ以外の処理は時間計測とその表示の処理です。着目しておくのは4行目のjQueryでセレクタにクラス属性を利用している点です(あとでid属性との差を確認します)

$("button").click(function(){
	var startTime = new Date();
	for (i = 0; i < 1000; i++) {
		$(".testArea").append(' ' + i);
	}
	var endTime = new Date();
	var msec = endTime - startTime;
	$("#timeArea").text(msec+"ミリ秒");
});

buttonをクリックすると処理を開始し、掛かった時間を表示します。計測結果は各人の環境によると思いますが、私の環境では「41ミリ秒」でした。

つづいてclass属性ではなく「id属性」を利用したサンプルを確認します。サンプル(speed/02.html)のソースを開いて、以下の様にtestAreaのdiv要素がid属性に変更されていることを確認して下さい。

<button>start</button>
<div id="timeArea"></div>
<div id="testArea"></div>

それに伴い、for文内のjQueryも以下の様にセレクタが変更されています。

for (i = 0; i < 1000; i++) {
	$("#testArea").append(' ' + i);
}

buttonをクリックして計測すると、私の環境では「23ミリ秒」とclass属性の時よりも半分くらいの時間で処理が終わりました。構成上class属性を利用しなければならない時もありますが、ページ内に1つしかない場合はid属性を利用して負荷を下げるようにしましょう

何度も利用するjQueryオブジェクトは変数に入れて利用する

サンプルspeed/02.htmlはさらに負荷を軽くできます。そもそもfor文の中で「$("#testArea")」と記述したら、testAreaのjQueryオブジェクト作成を1000回もすることになり、効率が良くありません。

ですから「$("#testArea")」の処理をfor文の外で実行し、その結果をfor文の中で利用します。サンプル(speed/03.html)のソースを開いて、for文の部分が以下の様に変更されていることを確認して下さい。

myTarget = $("#testArea");
for (i = 0; i < 1000; i++) {
	myTarget.append(' ' + i);
}

for文の外の1行目でjQueryオブジェクトを作成し変数「myTarget」に代入しています。そしてfor文内で変数「myTarget」を利用するようにしました。これでjQueryオブジェクトの作成は1回だけになります

結果として、buttonをクリックすると私の環境では「17ミリ秒」となり、より高速化されたことが確認できました。何度も利用するようなjQueryオブジェクトは、このように変数に入れて利用するようにしましょう。

トラバースによる高速化を検証(2013年9月 追記)

セレクタトラバースには同じような機能があり、トラバースを利用すると処理の高速化に貢献できると考えていたのですが、実際に利用すると効果は薄いことがわかりました。

サンプル(speed/04.html)を開いてjQueryを確認して下さい。前項で頻繁に利用するjQueryオブジェクトは変数に入れると高速化できると説明しましたが、この例では以下の様にjQueryオブジェクトが3つとも異なるため、1つの変数にまとめることができません。

$(".test").css("background-color", "#faa");
$(".test>ul").css("margin-left", "100px");
$(".test>ul>li").css("list-style-type", "none");

しかしトラバースを利用するとまとめることができます。サンプル(speed/04b.html)を開いてjQueryを確認して下さい。トラバースを利用すれば以下の様に最初のjQueryオブジェクトを変数に入れてもspeed/04.htmlと同じ処理ができます(次ページで紹介するメソッドチェーンを利用して1行で記述しています)。

var test = $(".test");//-----変数に入れる
var test.css("background-color", "#faa").children("ul").css("margin-left", "100px")
.children("li").css("list-style-type", "none");

しかし実際に処理時間を計測すると私の環境では2つの処理に差が出ませんでした(両方ともおよそ130ミリ秒)

メモ

描画負荷に考慮する

jQueryのサイトなので、jQueryの負荷について説明してきましが、コンテンツ作成で「より問題になる」のは描画負荷です。なぜなら描画負荷の方がjQueryオブジェクト作成の負荷よりもはるかに大きいからです

描画負荷とはディスプレイに何か表示するときにかかる負荷のことです。この描画負荷はPCの処理の中でも大きく、これを効率よく処理するために大抵のPCにはCPUの他にグラフィックボード/GPUを載せています。負荷に対応できないと、アニメーションがカクつく事になります。ですから余分な負荷をかけずに、可能な限り描画負荷を軽くするように心がける必要があります。

jQueryでのポイントは描画面積と半透明の描画です。大きな画像を移動させる場合はグラフィックメモリを大量に書き換える必要があるため負荷が大きくなります。また、半透明の画像は下の画像と計算して最終的な色を表示するため、通常よりも負荷がかかります。あと今はほとんど利用されていませんが、SVGのようなベクターデータはレンダリングに負荷がかかることになるでしょう。

ですから、大きなグラフィックを動かしたり、小さくてもたくさんのグラフィックを同時に動かすのは避けるようにします。また不用意に半透明のオブジェクトを利用するのも避けましょう

次回はjQueryオブジェクトを使いまわすメソッドチェーンについて説明します。