ホームページ  >  記事  >  ウェブフロントエンド  >  Javascriptの実行効率を徹底まとめ_基礎知識

Javascriptの実行効率を徹底まとめ_基礎知識

WBOY
WBOYオリジナル
2016-05-16 17:17:48976ブラウズ

JavaScript は非常に柔軟な言語であり、さまざまなスタイルのコードを自由に記述できます。開発プロセスでは、必然的に実行効率に違いが生じます。 、一般的で回避しやすい問題を整理します

JavaScript 自体の実行効率
JavaScript のスコープチェーン、クロージャー、プロトタイプ継承、eval などの機能は、さまざまな魔法の機能を提供するだけでなく、さまざまな効率上の問題も引き起こします。 、不用意に使用すると実行効率の低下につながります。

1. グローバルインポート
コーディングプロセス中に多かれ少なかれいくつかのグローバル変数(ウィンドウ、ドキュメント、カスタムグローバル変数など)を使用します。誰もが知っているように、ローカル スコープでグローバル変数にアクセスするには、トップレベルのスコープに至るまでスコープ チェーン全体を層ごとにたどる必要があり、ローカル変数へのアクセス効率はより高速かつ高くなるため、一部のグローバル オブジェクトはローカル スコープで頻繁に使用されます。スコープはローカル スコープにインポートできます。例:

コードをコピーします コードは次のとおりです:

//1. モジュール
をパラメータとして渡します (function(window,$){
var xxx = window.xxx;
$("#xxx1").xxx ();
$ ("#xxx2").xxx();
})(window,jQuery);

//2. ローカル変数に一時保存
function() {
var doc = document;
var global = window.global;
}

2. eval および eval に似た問題
eval が文字列を変換できることは誰もが知っています。これは js コードとして実行されます。eval を使用して実行されたコードは、eval を使用しないコードよりも 100 倍以上遅いと言われています (具体的な効率をテストしたことはありません。興味のある学生はテストしてみてください)。

JavaScript コードは、実行前に同様の「プリコンパイル」操作を実行します。まず、現在の実行環境でアクティブ オブジェクトを作成し、var で宣言された変数をアクティブ オブジェクトの属性として設定しますが、この時点では、変数の代入値はすべて未定義であり、function で定義された関数もアクティブ オブジェクトのプロパティとして追加され、その値は関数の定義とまったく同じになります。ただし、「eval」を使用すると、「eval」内のコード (実際には文字列) は事前にコンテキストを認識できず、事前に解析および最適化することができません。つまり、プリコンパイルされた操作を実行できません。したがって、パフォーマンスも大幅に低下します

実際、最近では eval を使用する人はほとんどいません。ここで説明したいのは、eval に似た 2 つのシナリオ (new Function{}、setTimeout、setInterver) です。

setTimtout("alert(1)",1000);
setInterver("alert(1)",1000);
(new Function("alert(1)"))(); >

上記の種類のコードは実行効率が比較的低いため、匿名メソッドまたはメソッド参照を setTimeout メソッドに直接渡すことをお勧めします

3. クロージャが終了したら、参照されなくなった変数を解放します

コードをコピーします コード次のように:
var f = (function(){
var a = {name:"var3"};
var b = ["var1","var2"];
var c = document.getElementByTagName("li");
//****その他の変数
//***一部の操作
var res = function(){
アラート( a.name);
}
return res;
})()

上記のコードの変数 f の戻り値は、即時関数で構成されるクロージャ内にあります。実行された関数が返されたメソッド res は、このクロージャ内のすべての変数 (a、b、c など) への参照を保持するため、これら 2 つの変数、特に DOM 要素への参照は常にメモリ空間に存在します。非常に大きく、res 内の変数の値のみを使用するため、クロージャが

var f = (function(){
var a = {name:"var3"};
var b = [" var1" ,"var2"];
var c = document.getElementByTagName("li");
//****その他の変数
//***一部の操作
//Close 変数を解放パッケージが
b = c = null;
var res = function(){
alter(a.name);
}
return res;})()


JS 操作 DOM の効率
Web 開発プロセスでは、フロントエンドの実行効率のボトルネックは、パフォーマンスを非常に重視する DOM 操作にあることがよくあります。 DOM 操作中のパフォーマンスを可能な限り節約することはできますか?

1. リフローを削減します
リフローとは何ですか?
DOM 要素の属性 (色など) が変更されると、ブラウザは対応する要素を再描画するように render に通知します。このプロセスは再描画と呼ばれます。

変更に要素のレイアウト (幅など) が含まれる場合、ブラウザーは元の属性を破棄し、再計算して結果をレンダリングに渡し、ページ要素を再描画します。このプロセスはリフローと呼ばれます。

リフローを軽減する方法
1. まずドキュメントから要素を削除し、修正が完了したら要素を元の位置に戻します (リフロー操作が多数実行された場合)要素とそのサブ要素に対する 2 つの方法 1 と 2 の効果がより明確になります)

2. 要素の表示を「なし」に設定し、表示を元の値に変更します。変更完了後

3 複数のスタイル属性を変更する場合は、スタイル属性を複数回変更する代わりにクラス クラスを定義します (特定の学生に推奨)

4. 大きなファイルを追加する場合は documentFragment を使用します。ページの要素数

たとえば

コードをコピーします コードは次のとおりです:

for( var i=0;i var child = docuemnt.createElement("li");
child.innerHtml = "child";
document.getElementById(" parent").appendChild(child);
}

上記のコードは dom を複数回操作することになり、比較的非効率的です。これを次の形式に変更して documentFragment を作成できます。 docuemntFragment へのすべての要素は dom 構造を変更せず、最後に 1 回のリフローでそれをページに追加します
コードをコピー コードは次のとおりです:

var frag = document.createDocumentFragment();
for(var i=0;i var child = docuemnt. createElement("li");
child.innerHtml = " child";
frag.appendChild(child);
}
document.getElementById("parent").appendChild(frag); 🎜>

2. DOM ステータス情報の一時保存
コードが要素のステータス情報に複数回アクセスする必要がある場合、ステータスが次の場合は変数に一時的に保存できます。これにより、DOM への複数のアクセスによって発生するメモリのオーバーヘッドを回避できます。典型的な例は次のとおりです。

コード コードは次のとおりです:
var lis = document.getElementByTagName ("li");
for(var i=1;i // ***
}

上記のメソッドは次のように各ループが dom 要素にアクセスします。

コードをコピーします コードは次のとおりです:
var lis = document.getElementByTagName("li");
for(var i=1 ,j=lis.length ;i //***
}


3. セレクターの検索範囲を狭める
DOM 要素を検索するときは、ページ要素の広い領域を走査しないようにするか、正確なセレクターを使用するか、コンテキストを指定して検索を絞り込みます。スコープ、jquery を例として取り上げます

• あいまい一致セレクターをあまり使用しないでください: たとえば、$("[name*='_fix']")、id などの複合セレクターを使用し、範囲を徐々に狭めます $("li.active ") など

•コンテキストを指定します: 例: $(“#parent .class”)、$(“.class”,$el) など

4. イベント委任を使用する
使用シナリオ: マウスのクリック後に特定の機能を実装するには、各レコードをクリック イベントにバインドする必要があります。通常のアプローチでは、リスニング イベントを各レコードにバインドします。このアプローチでは、ページ上に多数のイベント リスナーが作成され、比較的非効率的になります。

基本原則: DOM 仕様内のイベントがバブルアップすることは誰もが知っています。つまり、イベントのバブル化を積極的に防止しないと、任意の要素のイベントがバブル化されてしまいます。 DOM ツリーの構造に従って段階的に先頭に進みます。イベント オブジェクトには、イベント ソースを指すevent.target (IE の srcElement) も用意されているため、親要素でイベントをリッスンしても、イベントをトリガーした元の要素を見つけることができます。これが基本原理です。代表団。早速、例を示します。

コードをコピー コードは次のとおりです。

$ ("ul li ").bind("click",function(){
alert($(this).attr("data"));
})

上記の記述方法は実際には、すべての li 要素が各要素のマウス クリックをリッスンするクリック イベントにバインドされているため、ページ上に多数のイベント リスナーが存在します。

上で紹介したイベント監視の原理に従って、書き換えてみましょう

コードをコピーします コードは次のとおりです。

$("ul").bind("click",function(e){
if(e.target.nodeName.toLowerCase() ==="li"){
alert($( e.target).attr("data"));
}
})

这样一来,我们就可以只添加一个事件监听器去捕获所有li上触发的事件,并做出相应的操作。

当然,我们不必每次都做事件源的判断工作,可以将其抽象一下交给工具类来完成。jquery中的delegate()方法就实现了该功能

语法是这样的$(selector).delegate(childSelector,event,data,function),例如:

$("div").delegate("button","click",function(){
$("p").slideToggle();
});パラメータの説明 (w3school より引用)



参数 描述
childSelector 必需。规定要附加事件处理程序的一个或多个子元素。
event 必需。规定附加到元素的一个或多个事件。由空格分隔多个事件值。必须是有效的事件。
data 可选。规定传递到函数的额外数据。
function 必需。规定当事件发生时运行的函数。
ヒント: イベント委任のもう 1 つの利点は、イベント バインド後に動的に追加された要素でトリガーされたイベントも監視できるため、ページに動的に要素が追加されるたびに要素をバインドする必要がないことです。
声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。