9つの方法でjQueryコードの詳細を最適化
8249 ワード
ペアセレクタ
jQueryでは、複数のセレクタを使用して、同じページ要素を選択できます.各セレクタのパフォーマンスは異なり、パフォーマンスの違いを理解する必要があります.
1、最も速いセレクタ:idセレクタと要素ラベルセレクタ
たとえば、次の文のパフォーマンスが最適です.
これらのセレクタに遭遇すると、jQuery内部でブラウザのオリジナルメソッド(getElementById()など)が自動的に呼び出されるため、実行速度が速くなります.
2、遅いセレクタ:classセレクタ
$('.className')のパフォーマンスは、ブラウザによって異なります.Firefox、Safari、Chrome、Operaブラウザは、いずれもオリジナルメソッドgetElementByClassName()があるので、速度は遅くありません.しかし、IE 5-IE 8はこの方法を導入していないため、このセレクタはIEでかなり遅い
3、最も遅いセレクタ:擬似クラスセレクタと属性セレクタ
ページ内のすべての非表示要素を検索するには、擬似クラスセレクタを使用します.
プロパティ・セレクタの例は、次のとおりです.
ブラウザには元の方法がないため、この2つの文が最も遅いです.しかし、一部のブラウザの新しいバージョンでは、querySelector()とquerySelectorAll()メソッドが追加されているため、このようなセレクタのパフォーマンスが大幅に向上します.
親子関係の理解
次の6つのセレクタは、親要素から子要素を選択します.
1、次の文の意味は、DOMオブジェクトを指定し、その中からサブ要素を選択することです.jQueryはこの文を自動的に$に変換します.parent.find('child')は、一定のパフォーマンス損失をもたらします.最も速い形式より5%-10%遅いです
2、これは一番速い文です.find()メソッドはブラウザのオリジナルメソッド(getElementById,getElementByName,getElementByTagNameなど)を呼び出すので、速度が速い
3、この文はjQueryの内部にあり、$が使用されます.Sibling()とjavascriptのnextSibling()メソッドは、ノードを1つずつ巡回します.最も速い形より約50%遅いです
4、jQuery内部はSizzleエンジンを使用し、各種セレクタを処理する.Sizzleエンジンの選択順序は右から左なので、この文は先に選択します.childは、親要素parentをさらにフィルタリングし、最も速い形式より約70%遅い
5、この文は前の文と同じです.しかし、前のサブエレメントは直接のサブエレメントのみを選択し、これはマルチレベルのサブエレメントを選択できるので、その速度はもっと遅く、最も速い形式より77%遅いかもしれません.
6、jQuery内部ではこの文を$('#parent')に変換します.find('.child')は、最も速い形式より23%遅い
だから、最適な選択は$parentです.find('.child').また,$parentは往々にして前の操作で生成され,jQueryはキャッシュされるため,実行速度がさらに速くなる.
jQueryを過度に使用しない
jQueryの速度がいくら速くても、オリジナルのjavascriptメソッドとは比べものになりません.原生的な方法で使える場合は、jQueryは避けましょう.
最も簡単なセレクタを例にとるとdocument.getElementById(「foo」)は$(「#foo」)より10倍以上速い
もう1つの例を見て、a要素にクリックイベントを処理する関数をバインドします.
このコードの意味は、a要素をクリックすると、その要素のid属性がポップアップされます.この属性を取得するには、jQueryを2回連続して呼び出す必要があります.1回目は$(this)、2回目はattr('id')です.
実際、このような処理は全く必要ありません.より正確な書き方はjavascriptのオリジナルメソッドを直接採用し、thisを呼び出すことです.id:
テストによるとidの速度比$(this).attr('id')は20倍以上速くなりました
キャッシュを作成
Web要素を選択すると、コストがかかります.したがって、セレクタを使用する回数は少ないほうがよいし、選択した結果をできるだけキャッシュし、後で繰り返し使用するのに便利である.
例えば、次のような書き方は悪い書き方です.
もっと良い書き方は:
テストによると、キャッシュはキャッシュしないより2~3倍速い
jQueryの大きな特徴は、チェーン式の書き方を許可することです
チェーン書き方を採用する場合、jQueryは各ステップの結果を自動的にキャッシュするので、非チェーン書き方よりも速い.テストによると、チェーン書き方は(キャッシュを使用しない)非チェーン書き方より約25%速い.
イベントの委任
JAvascriptのイベントモデルは、「バブル」モードを採用しています.つまり、サブエレメントのイベントは段階的に「バブル」し、親エレメントのイベントになります.
これにより,イベントのバインドを大幅に簡素化できる.例えば、100個の格子(td要素)が入ったテーブル(table要素)があります.現在、各格子にクリックイベント(click)をバインドするように要求されていますが、次のコマンドを100回実行する必要がありますか?
答えは必要ありません.私たちはこのイベントをtable要素の上にバインドすればいいです.td要素がクリックイベントを発生した後、このイベントは親要素tableの上に「泡が立つ」ので、傍受されます.
したがって、このイベントは親要素を100回バインドする必要がなく、親要素を1回バインドするだけで済むため、パフォーマンスが大幅に向上します.これをイベントの「委任処理」と呼びます.つまり、サブエレメントの「委任」親エレメントがこのイベントを処理します.
より良い方法は、documentオブジェクトにイベントをバインドすることです.
イベントのバインドを解除する場合はoff()メソッドを使用します.
少ない変更DOM
1.DOMの構造変更はコストがかかるので、頻繁に使用することはない.append()、.InsertBefore()と.insetafter()という方法
複数の要素を挿入する場合は、まずそれらを結合してから、一度に挿入します.テストによると、マージ挿入はマージしない挿入よりも10倍近く速くなりました.
2.一つのDOM元素を大量に処理する場合は、先に用いるべきである.detach()メソッドは、この要素をDOMから取り出し、処理が完了したら、ドキュメントに再挿入します.テストに基づいて、使用します.detach()メソッドは使用しない場合より60%速くなりました
3、DOM要素にデータを保存する場合は、次のように書かないでください.
書く
テストによると、後者の書き方は前の書き方より10倍近く速くなった.なぜならData()メソッドは、jQuery関数のprototypeオブジェクト上に定義、$である.Data()メソッドはjQuery関数上を定義しており,呼び出す際に複雑なjQueryオブジェクトから呼び出さないため,より高速である.
4、htmlコードを挿入するとき、ブラウザのオリジナルのinnterHTML()メソッドはjQueryオブジェクトのhtml()よりも速い
jQueryオブジェクトの生成を最小限に抑える
セレクタ($('#id')など)を使用するたびに、jQueryオブジェクトが生成されます.jQueryオブジェクトは膨大なオブジェクトであり、多くの属性と方法があり、多くのリソースを占有します.したがって、jQueryオブジェクトの生成を最小限に抑える
たとえば、多くのjQueryメソッドには、jQueryオブジェクトで使用されるバージョンと、jQuery関数で使用されるバージョンの2つのバージョンがあります.次の2つの例は,いずれも1つの要素のテキストを取り出し,text()メソッドを用いる.
jQueryオブジェクトのバージョンを使用することもできます.
jQuery関数のバージョンも使用できます.
後者のjQuery関数のバージョンはjQueryオブジェクトによって操作されないため、相対的にオーバーヘッドが小さく、速度が速い
役割ドメインチェーンが最も短い方法を選択
厳密に言えば、この原則はjQueryだけでなく、すべてのJavascriptプログラミングに適用されます.
Javascriptの変数はチェーン型の役割ドメインを採用していることを知っています.変数を読み込むときは、まず現在の役割ドメインで変数を探し、見つからない場合は前のレイヤの役割ドメインで変数を探します.このような設計により、ローカル変数の読み取りがグローバル変数の読み取りよりもずっと速くなる
次の2つのコードを見てください.最初のコードはグローバル変数を読み込むことです.
2番目のセグメントコードは、ローカル変数を読み込みます.
2段目のコードが変数aを読み取る場合は、上の層の役割ドメインに行かなくてもよいので、1段目のコードより5、6倍速くなります
同様に、オブジェクトメソッドを呼び出す場合、closureモードはprototypeモードよりも速くなります.
prototypeモード:
closureモード:
同じくget_name()メソッド、closureモードの方が速い
Pub/subモードでイベントを管理する
イベントが発生した後、複数の操作を連続的に実行する場合は、次のように書かないほうがいいです.
では、イベントトリガの形式を変更します.
deferredオブジェクトの使用も考えられます
jQueryコードの最適化方法については、次のリンクをクリックしてください.
jQueryでは、複数のセレクタを使用して、同じページ要素を選択できます.各セレクタのパフォーマンスは異なり、パフォーマンスの違いを理解する必要があります.
1、最も速いセレクタ:idセレクタと要素ラベルセレクタ
たとえば、次の文のパフォーマンスが最適です.
$('#id')
$('form')
$('input')
これらのセレクタに遭遇すると、jQuery内部でブラウザのオリジナルメソッド(getElementById()など)が自動的に呼び出されるため、実行速度が速くなります.
2、遅いセレクタ:classセレクタ
$('.className')のパフォーマンスは、ブラウザによって異なります.Firefox、Safari、Chrome、Operaブラウザは、いずれもオリジナルメソッドgetElementByClassName()があるので、速度は遅くありません.しかし、IE 5-IE 8はこの方法を導入していないため、このセレクタはIEでかなり遅い
3、最も遅いセレクタ:擬似クラスセレクタと属性セレクタ
ページ内のすべての非表示要素を検索するには、擬似クラスセレクタを使用します.
$(':hidden')
プロパティ・セレクタの例は、次のとおりです.
$('[attribute=value]')
ブラウザには元の方法がないため、この2つの文が最も遅いです.しかし、一部のブラウザの新しいバージョンでは、querySelector()とquerySelectorAll()メソッドが追加されているため、このようなセレクタのパフォーマンスが大幅に向上します.
親子関係の理解
次の6つのセレクタは、親要素から子要素を選択します.
$('.child', $parent)
$parent.find('.child')
$parent.children('.child')
$('#parent > .child')
$('#parent .child')
$('.child', $('#parent'))
1、次の文の意味は、DOMオブジェクトを指定し、その中からサブ要素を選択することです.jQueryはこの文を自動的に$に変換します.parent.find('child')は、一定のパフォーマンス損失をもたらします.最も速い形式より5%-10%遅いです
$('.child', $parent)
2、これは一番速い文です.find()メソッドはブラウザのオリジナルメソッド(getElementById,getElementByName,getElementByTagNameなど)を呼び出すので、速度が速い
$parent.find('.child')
3、この文はjQueryの内部にあり、$が使用されます.Sibling()とjavascriptのnextSibling()メソッドは、ノードを1つずつ巡回します.最も速い形より約50%遅いです
$parent.children('.child')
4、jQuery内部はSizzleエンジンを使用し、各種セレクタを処理する.Sizzleエンジンの選択順序は右から左なので、この文は先に選択します.childは、親要素parentをさらにフィルタリングし、最も速い形式より約70%遅い
$('#parent > .child')
5、この文は前の文と同じです.しかし、前のサブエレメントは直接のサブエレメントのみを選択し、これはマルチレベルのサブエレメントを選択できるので、その速度はもっと遅く、最も速い形式より77%遅いかもしれません.
$('#parent .child')
6、jQuery内部ではこの文を$('#parent')に変換します.find('.child')は、最も速い形式より23%遅い
$('.child', $('#parent'))
だから、最適な選択は$parentです.find('.child').また,$parentは往々にして前の操作で生成され,jQueryはキャッシュされるため,実行速度がさらに速くなる.
jQueryを過度に使用しない
jQueryの速度がいくら速くても、オリジナルのjavascriptメソッドとは比べものになりません.原生的な方法で使える場合は、jQueryは避けましょう.
最も簡単なセレクタを例にとるとdocument.getElementById(「foo」)は$(「#foo」)より10倍以上速い
もう1つの例を見て、a要素にクリックイベントを処理する関数をバインドします.
$('a').click(function(){
alert($(this).attr('id'));
});
このコードの意味は、a要素をクリックすると、その要素のid属性がポップアップされます.この属性を取得するには、jQueryを2回連続して呼び出す必要があります.1回目は$(this)、2回目はattr('id')です.
実際、このような処理は全く必要ありません.より正確な書き方はjavascriptのオリジナルメソッドを直接採用し、thisを呼び出すことです.id:
$('a').click(function(){
alert(this.id);
});
テストによるとidの速度比$(this).attr('id')は20倍以上速くなりました
キャッシュを作成
Web要素を選択すると、コストがかかります.したがって、セレクタを使用する回数は少ないほうがよいし、選択した結果をできるだけキャッシュし、後で繰り返し使用するのに便利である.
例えば、次のような書き方は悪い書き方です.
jQuery('#top').find('p.classA');
jQuery('#top').find('p.classB');
もっと良い書き方は:
var cached = jQuery('#top');
cached.find('p.classA');
cached.find('p.classB');
テストによると、キャッシュはキャッシュしないより2~3倍速い
jQueryの大きな特徴は、チェーン式の書き方を許可することです
$('div').find('h3').eq(2).html('Hello');
チェーン書き方を採用する場合、jQueryは各ステップの結果を自動的にキャッシュするので、非チェーン書き方よりも速い.テストによると、チェーン書き方は(キャッシュを使用しない)非チェーン書き方より約25%速い.
イベントの委任
JAvascriptのイベントモデルは、「バブル」モードを採用しています.つまり、サブエレメントのイベントは段階的に「バブル」し、親エレメントのイベントになります.
これにより,イベントのバインドを大幅に簡素化できる.例えば、100個の格子(td要素)が入ったテーブル(table要素)があります.現在、各格子にクリックイベント(click)をバインドするように要求されていますが、次のコマンドを100回実行する必要がありますか?
$("td").on("click", function(){
$(this).toggleClass("click");
});
答えは必要ありません.私たちはこのイベントをtable要素の上にバインドすればいいです.td要素がクリックイベントを発生した後、このイベントは親要素tableの上に「泡が立つ」ので、傍受されます.
したがって、このイベントは親要素を100回バインドする必要がなく、親要素を1回バインドするだけで済むため、パフォーマンスが大幅に向上します.これをイベントの「委任処理」と呼びます.つまり、サブエレメントの「委任」親エレメントがこのイベントを処理します.
$("table").on("click", "td", function(){
$(this).toggleClass("click");
});
より良い方法は、documentオブジェクトにイベントをバインドすることです.
$(document).on("click", "td", function(){
$(this).toggleClass("click");
});
イベントのバインドを解除する場合はoff()メソッドを使用します.
$(document).off("click", "td");
少ない変更DOM
1.DOMの構造変更はコストがかかるので、頻繁に使用することはない.append()、.InsertBefore()と.insetafter()という方法
複数の要素を挿入する場合は、まずそれらを結合してから、一度に挿入します.テストによると、マージ挿入はマージしない挿入よりも10倍近く速くなりました.
2.一つのDOM元素を大量に処理する場合は、先に用いるべきである.detach()メソッドは、この要素をDOMから取り出し、処理が完了したら、ドキュメントに再挿入します.テストに基づいて、使用します.detach()メソッドは使用しない場合より60%速くなりました
3、DOM要素にデータを保存する場合は、次のように書かないでください.
var elem = $('#elem');
elem.data(key,value);
書く
var elem = $('#elem');
$.data(elem[0],key,value);
テストによると、後者の書き方は前の書き方より10倍近く速くなった.なぜならData()メソッドは、jQuery関数のprototypeオブジェクト上に定義、$である.Data()メソッドはjQuery関数上を定義しており,呼び出す際に複雑なjQueryオブジェクトから呼び出さないため,より高速である.
4、htmlコードを挿入するとき、ブラウザのオリジナルのinnterHTML()メソッドはjQueryオブジェクトのhtml()よりも速い
jQueryオブジェクトの生成を最小限に抑える
セレクタ($('#id')など)を使用するたびに、jQueryオブジェクトが生成されます.jQueryオブジェクトは膨大なオブジェクトであり、多くの属性と方法があり、多くのリソースを占有します.したがって、jQueryオブジェクトの生成を最小限に抑える
たとえば、多くのjQueryメソッドには、jQueryオブジェクトで使用されるバージョンと、jQuery関数で使用されるバージョンの2つのバージョンがあります.次の2つの例は,いずれも1つの要素のテキストを取り出し,text()メソッドを用いる.
jQueryオブジェクトのバージョンを使用することもできます.
var $text = $("#text");
var $ts = $text.text();
jQuery関数のバージョンも使用できます.
var $text = $("#text");
var $ts = $.text($text);
後者のjQuery関数のバージョンはjQueryオブジェクトによって操作されないため、相対的にオーバーヘッドが小さく、速度が速い
役割ドメインチェーンが最も短い方法を選択
厳密に言えば、この原則はjQueryだけでなく、すべてのJavascriptプログラミングに適用されます.
Javascriptの変数はチェーン型の役割ドメインを採用していることを知っています.変数を読み込むときは、まず現在の役割ドメインで変数を探し、見つからない場合は前のレイヤの役割ドメインで変数を探します.このような設計により、ローカル変数の読み取りがグローバル変数の読み取りよりもずっと速くなる
次の2つのコードを見てください.最初のコードはグローバル変数を読み込むことです.
var a = 0;
function x(){
a += 1;
}
2番目のセグメントコードは、ローカル変数を読み込みます.
function y(){
var a = 0;
a += 1;
}
2段目のコードが変数aを読み取る場合は、上の層の役割ドメインに行かなくてもよいので、1段目のコードより5、6倍速くなります
同様に、オブジェクトメソッドを呼び出す場合、closureモードはprototypeモードよりも速くなります.
prototypeモード:
var X = function(name){ this.name = name; }
X.prototype.get_name = function() { return this.name; };
closureモード:
var Y = function(name) {
var y = { name: name };
return { 'get_name': function() { return y.name; } };
};
同じくget_name()メソッド、closureモードの方が速い
Pub/subモードでイベントを管理する
イベントが発生した後、複数の操作を連続的に実行する場合は、次のように書かないほうがいいです.
function doSomthing{
doSomethingElse();
doOneMoreThing();
}
では、イベントトリガの形式を変更します.
function doSomething{
$.trigger("DO_SOMETHING_DONE");
}
$(document).on("DO_SOMETHING_DONE", function(){
doSomethingElse();
});
deferredオブジェクトの使用も考えられます
function doSomething(){
var dfd = new $.Deferred();
//Do something async, then...
//dfd.resolve();
return dfd.promise();
}
function doSomethingElse(){
$.when(doSomething()).then(//The next thing);
}
jQueryコードの最適化方法については、次のリンクをクリックしてください.