Pourquoi est une itération à travers un tableau plus rapide vers l'arrière que vers l'avant
Étant donné ce code:
var arr = [];
for (var i = 0; i < 10000; ++i)
arr.push(1);
Transmet
for (var i = 0; i < arr.length; ++i) {}
En arrière
for (var i = arr.length - 1; i >= 0; --i) {}
Codée en dur de l'Avant
for (var i = 0; i < 10000; ++i) {}
Pourquoi est vers l'arrière de manière beaucoup plus rapide?
Voici le test:
http://jsperf.com/array-iteration-direction
- Notez que votre arrière de cas devrait commencer à
arr.length-1
et onti >= 0
plutôt quei > 0
. - Le titre est trompeur. Il n'est plus le cas, directement à l'aide de arr.la longueur est plus lente avancée dans les navigateurs.
- double possible de JavaScript performance de la boucle - Pourquoi est-à décrémenter l'itérateur vers 0 plus vite que l'incrémentation
Vous devez vous connecter pour publier un commentaire.
Parce que votre avant-condition pour recevoir la
length
propriété de votre tableau à chaque fois, tandis que l'autre n'a qu'à cocher pour "supérieure à zéro", un très rapide de tâche.Lorsque votre longueur du tableau ne change pas au cours de la boucle, et vous regardez vraiment ns performance, vous pouvez utiliser
BTW: au Lieu de
for (var i = arr.length; i > 0; --i)
vous pouvez utiliserfor (var i = arr.length; i-- > 0; )
qui fonctionne vraiment par l'intermédiaire de votre tableau de n-1 à 0, pas de n à 1.for(... ; i-- ;)
i<l
est un autre calcul quei>0
, mais oui, ils sont plutôt égale (plus rapide que le cache de la longueur): jsperf.com/array-iteration-direction/3 - pourtant, certains moteurs de reconnaître et d'optimiser certains de ces casvar i = 0; var a = i < 10; while(a) { i++; a = i < 10; }
.for (var i = arr.length; i-- > 0; )
va manquer l'indice 0 1-- !>0? peut-être que ce doit êtrefor (var i = arr.length; i-- >= 0; )
i
dans le corps de la boucle (après avoir été décrémenté) est toujours plus petit que lei
vu dans la condition (avant d'être décrémentée). Ce que vous avez besoin estfor (var i=arr.length-1; i>=0; --i)
i
, puis la compare à 0, puis décide de faire de l'itération ou pas. Comme cela, il semble que 1 doit être décrémenté à 0, donc pas de départ de l'itération comme il n'est pas > 0Parce que dans le premier formulaire, vous êtes accédant à la propriété
length
de la matricearr
une fois pour chaque itération, alors que dans le second vous ne le faites qu'une fois.Si vous voulez les avoir au même rythme, vous pouvez le faire pour l'avenir de l'itération;
Donc, votre script n'aurez pas besoin de prendre la longueur de la matrice sur everystep.
Je ne suis pas entièrement sûr de cela, mais voici ma conjecture:
Pour le code suivant:
Au cours de l'exécution, il y a un arr.calcul de la longueur après chaque tour de boucle. Cela peut être une opération triviale quand il est seul, mais peut avoir un impact quand il s'agit de plusieurs tableaux de grande. Pouvez-vous essayer le suivant:
Dans le code ci-dessus, on calcule la longueur du tableau, juste une fois, et de fonctionner avec que le calcul de nombre, plutôt que d'effectuer la longueur de calcul de plus et plus de nouveau.
De nouveau, juste de mettre mes pensées ici. Observation intéressante en effet!
i > 0
est plus rapide quei < arr.length
et se produit à chaque itération de la boucle.Vous pouvez atténuer la différence:
Ce n'est pas encore aussi rapide que le vers l'arrière de l'élément, mais plus rapide que votre option.
faire comme ci-dessous, il fonctionnera de la même façon. parce que
arr.length
prend du temps à chaque itération de l'avant.avant
arrière
for(i=len; --i>=0;){
for (let i = arr.length; i-- > 0;) {
Et elles sont aussi bonnes:
OU
while(--L>=0) arr[L] = L;