このコードを考えます:
var arr = [];
for (var i = 0; i < 10000; ++i)
arr.Push(1);
フォワード
for (var i = 0; i < arr.length; ++i) {}
後方
for (var i = arr.length - 1; i >= 0; --i) {}
ハードコード化されたフォワード
for (var i = 0; i < 10000; ++i) {}
なぜ逆方向にこれほど高速なのですか?
テストは次のとおりです。 http://jsperf.com/array-iteration-direction
Forwards-conditionは毎回配列のlength
プロパティを受け取る必要があるため、他の条件は "greater then zero"(非常に高速なタスク)のみをチェックする必要があります。
ループ中に配列の長さが変わらず、実際にns-perfomanceを見る場合、次を使用できます。
_for (var i=0, l=arr.length; i<l; i++)
_
ところで:for (var i = arr.length; i > 0; --i)
の代わりに、n [1]ではなく、n-1から0まで実際に配列を実行するfor (var i = arr.length; i-- > 0; )
を使用できます。
最初のフォームでは、配列length
のプロパティarr
に繰り返しアクセスするたびに1回アクセスするのに対し、2番目のフォームでは1回だけアクセスするためです。
それらを同じペースにしたい場合は、前方反復でそれを行うことができます。
for(var i=0, c=arr.length; i<c; i++){
}
したがって、スクリプトはすべてのステップで配列の長さを取る必要はありません。
私はこれについて完全に確信していませんが、ここに私の推測があります:
次のコードの場合:
for (var i = 0; i < arr.length; ++i) {;
}
実行時に、各ループパスの後にarr.lengthの計算があります。これは、スタンドアロンの場合は簡単な操作かもしれませんが、複数/巨大なアレイの場合は影響があります。以下を試すことができます:
var numItems = arr.length;
for(var i=0; i< numItems; ++i)
{
}
上記のコードでは、配列の長さを一度だけ計算し、長さの計算を何度も実行するのではなく、その計算された数で操作します。
繰り返しますが、ここに私の考えを述べます。本当に興味深い観察!
i > 0
はi < arr.length
よりも高速で、ループの各反復で発生します。
これで違いを緩和できます:
for (var i = 0, len = arr.length; i < len; ++i) {;
}
これは、後方アイテムほど高速ではありませんが、前方オプションより高速です。
そして、これらも同様に良いです:
var arr= [], L= 10000;
while(L>-1) arr[L]= L--;
OR
var arr= [], i= 0;
while(i<10001) arr[i]=i++;
以下のように実行すると、同じ方法で実行されます。なぜならarr.length
は、各反復で時間がかかります。
int len = arr.length;
転送
for (var i = 0; i < len; ++i) {
}
後方
for (var i = len; i > 0; --i) {
}