ループはほとんどのプログラミング言語が持つ基本的な機能ですが、JS も例外ではありません。違いは、JS はインタープリタ型言語であり、クライアントのソフトウェアとハードウェアの条件が実行効率に大きく影響します。 JSの。ただし、クライアント環境は未知で多様で、開発者にとって変更するのが難しいため、コードの品質を最適化することがコードの効率を向上させる主な方法になります。
JS コードでは、ループはパフォーマンスの問題を引き起こしやすい要因です。ループの特性を理解し、的を絞った方法で最適化すると、パフォーマンスが大幅に向上する可能性があります。
For、while、do-while ループ:
これら 3 つのループのループ効率は似ているため、適切なアプリケーション シナリオに従って選択するだけで済みます。
for ループを例に挙げます。
var aValues = ["a", "b", "c", "d"];
for(var i = 0; i
fDoSomethingA(aValues[i]) ;
fDoSomethingA(aValues[i]);
}
上記の例では、各ループは i と配列の長さを比較する必要があります。したがって、配列の長さは毎回再読み取りする必要があります。配列の長さがループ中に一定であれば、これを行う必要はなく、長さを読み取る代わりにローカル変数を使用できるためです。同様に、この例では、aValues[i] が 2 回以上読み取られているため、それをローカル変数に割り当てることもできます:
var aValues = ["a", "b", "c", "d"], nLength = aValues.length;
for(var i = 0, sValue; i sValue = aValues[i];
fDoSomethingA(sValue);
fDoSomethingB(sValue);
}
ループのビジネス ロジックがループ順序に影響されない場合は、逆ループ、つまりカウンターを 0 にデクリメントしてみることができます。
var aValues = ["a" , "b", "c", "d"], nLength = aValues.length;
for(var i = nLength, sValue; i -= 1;){
sValue = aValues[i];
fDoSomethingA(sValue );
fDoSomethingB(sValue);
}
このメソッドを使用すると、デフォルトでカウンターは 0 と比較され、ローカル変数の比較も省略されます。理論的には効率を向上させることができます。
for-in ループ:
for-in ループは、オブジェクト プロパティをトラバースするために使用され、プロトタイプ チェーンの先頭まで継続されることがわかっています。ループ効率が低下します。 for-in ループの記述方法には最適化の余地がないため、for-in ループを使用する場合は特定の原則に従う必要があります。つまり、データ オブジェクトを走査する場合にのみ for-in ループを使用するようにしてください。
走査されるオブジェクトのプロパティが明確な場合は、代わりに配列ループを使用できます。
たとえば、連絡先オブジェクトを走査します:
var aContact = ["N", "FN", "EMAIL;PREF", ...];
for(var i = aContact.length; i -= 1;){
fDoSomething(aContact [i]) ;
}
ダフ戦略
ダフ戦略の主な原則は、ループを展開することで回数を減らして効率を向上させることです。たとえば
通常のループ:
for(var i = aValues.length; i -= 1){
fDoSomething(aValues[i]);
}
aValues.length == N の場合、次のように書くとループより上位になります:
fDoSomething(aValues[0]);
fDoSomething(aValues[1]);
fDoSomething(aValues[2]);
fDoSomething(aValues[3]);
.. .
...
fDoSomething(aValues[N-1]);
しかし、N が大きい場合、この書き方は非現実的であり、Duff 戦略は適度なループ展開になります。戦略。
最近、NetEase メールボックス連絡先の初期化サイクルに Duff 戦略が追加されました:
var nLength = aContacts.length,
//総ラウンド数
nRounds = Math.floor( nLength / 8),
// 追加マージン
nLeft = nLength % 8,
i = 0;
// 最初に残りを処理します
if(nLeft){
do{
fFormat(aContacts[i ]);
}while(-- nLeft)
}
//ラウンドごとに 8 回フォーマットを実行します
if(nRounds){
do{
fFormat(aContacts[i ]);
fFormat(aContacts[i ] );
fFormat(aContacts[i ]);
fFormat(aContacts[i ]);
fFormat(aContacts[i ]);
fFormat(aContacts[i ]);
fFormat (aContacts[i ]);
fFormat(aContacts[i ]);
}while(-- nRounds)
}
上記のように、ループの各ラウンドは8 つの接点データに対してフォーマット操作を実行し、ループを使用して残りの接点を処理します。接触が多い場合、総サイクル数が大幅に減少し、サイクル消費を削減できることがわかります。なお、8はDuff戦略により提案された最適値である。
実際のテストでは、IE では 10 ~ 20% 以上のパフォーマンス向上をもたらすことがわかりましたが、IE 以外のブラウザではほとんど違いがありません。
結論: テスト中に、IE 以外のブラウザーでは、最適化後と最適化前の効率の差はそれほど大きくないか、無視できるほどであることがわかりました。これは、これらのブラウザーの JS エンジンが小さいことを示しています。