web-dev-qa-db-ja.com

配列を順方向よりも逆方向に速く反復する理由

このコードを考えます:

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

50
samccone

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; )を使用できます。

81
Bergi

最初のフォームでは、配列lengthのプロパティarrに繰り返しアクセスするたびに1回アクセスするのに対し、2番目のフォームでは1回だけアクセスするためです。

8
rabusmar

それらを同じペースにしたい場合は、前方反復でそれを行うことができます。

for(var i=0, c=arr.length; i<c; i++){
}

したがって、スクリプトはすべてのステップで配列の長さを取る必要はありません。

6
tcak

私はこれについて完全に確信していませんが、ここに私の推測があります:

次のコードの場合:

for (var i = 0; i < arr.length; ++i) {;
}

実行時に、各ループパスの後にarr.lengthの計算があります。これは、スタンドアロンの場合は簡単な操作かもしれませんが、複数/巨大なアレイの場合は影響があります。以下を試すことができます:

 var numItems = arr.length;
    for(var i=0; i< numItems; ++i)
    {
    }

上記のコードでは、配列の長さを一度だけ計算し、長さの計算を何度も実行するのではなく、その計算された数で操作します。

繰り返しますが、ここに私の考えを述べます。本当に興味深い観察!

4
Gopal Nair

i > 0i < arr.lengthよりも高速で、ループの各反復で発生します。

これで違いを緩和できます:

for (var i = 0, len = arr.length; i < len; ++i) {;
}

これは、後方アイテムほど高速ではありませんが、前方オプションより高速です。

2
jfriend00

そして、これらも同様に良いです:

var arr= [], L= 10000;
while(L>-1) arr[L]= L--;

OR

var arr= [], i= 0;
while(i<10001) arr[i]=i++;
1
kennebec

以下のように実行すると、同じ方法で実行されます。なぜならarr.lengthは、各反復で時間がかかります。

int len = arr.length;

転送

for (var i = 0; i < len; ++i) {
}

後方

for (var i = len; i > 0; --i) {
}
1
dku.rajkumar