J'ai appris de livres que vous devriez écrire pour la boucle comme ceci:
for(var i=0, len=arr.length; i < len; i++){
// blah blah
}
de sorte que le arr.length
ne sera pas calculé à chaque fois.
D'autres disent que le compilateur va optimiser certaines choses, vous pouvez donc écrire:
for(var i=0; i < arr.length; i++){
// blah blah
}
Je veux juste savoir quelle est la meilleure façon de faire?
Après avoir effectué ce test avec la plupart des navigateurs modernes ...
Actuellement , la forme de boucle la plus rapide (et à mon avis la plus évidente du point de vue de la syntaxe).
une norme pour la mise en cache avec longueur
for (var i = 0, len = myArray.length; i < len; i++) {
}
Je dirais que c’est définitivement un cas où j’applaudis aux développeurs de moteurs JavaScript. Un temps d'exécution doit être optimisé pour clarté , et non pas habile .
Le moyen le plus rapide de parcourir un tableau javascript est le suivant:
var len = arr.length;
while (len--) {
// blah blah
}
Voir http://blogs.Oracle.com/greimer/entry/best_way_to_code_a pour une comparaison complète.
À compter de juin 2016, effectuant quelques tests dans le dernier Chrome (71% du marché des navigateurs en mai 2016 et en augmentation):
Je crois que ce fil est trop ancien et il est trompeur pour les programmeurs de penser qu'ils ont besoin de mettre en cache la longueur ou d'utiliser des passes inverses avec des diminutions pour obtenir de meilleures performances, en écrivant du code moins lisible et plus sujet aux erreurs qu'une simple boucle for simple. Par conséquent, je recommande:
Si votre application effectue une itération sur un grand nombre d'éléments ou si votre code de boucle est contenu dans une fonction utilisée fréquemment, une simple boucle for est la solution:
for (var i = 0; i < arr.length; i++) {
// Do stuff with arr[i] or i
}
Si votre application ne parcoure pas vraiment de nombreux éléments ou si vous devez simplement faire de petites itérations ici et là, utiliser le standard forChaque rappel ou toute fonction similaire de la bibliothèque JS de votre choix peut être plus compréhensible et moins sujet aux erreurs, car la variable d'index scope est fermée et vous n'avez pas besoin d'utiliser des crochets pour accéder directement à la valeur du tableau:
arr.forEach(function(value, index) {
// Do stuff with value or index
});
Si vous avez vraiment besoin de parcourir quelques millisecondes tout en parcourant des milliards de lignes et que la longueur de votre tableau ne change pas dans le processus, vous pouvez envisager de mettre en cache la longueur dans votre boucle for. Bien que je pense que ce n'est vraiment pas nécessaire de nos jours:
for (var i = 0, len = arr.length; i < len; i++) {
// Do stuff with arr[i]
}
Si la commande n'est pas importante, je préfère ce style:
for(var i = array.length; i--; )
Il cache la longueur et est beaucoup plus court à écrire. Mais il va parcourir le tableau dans l'ordre inverse.
Nous sommes en 2018, alors une mise à jour pourrait être Nice ...
Et je dois vraiment être en désaccord avec la réponse acceptée . Il diffère sur différents navigateurs. certains font forEach
plus vite, certains for-loop
, et certains while
voici un repère sur toutes les méthodes http://jsben.ch/mW36e
arr.forEach( a => {
// ...
}
et puisque vous pouvez voir beaucoup de boucles for-like telles que for(a = 0; ... )
, il est utile de mentionner que sans variables 'var', elles seront définies globalement et que cela peut considérablement affecter la vitesse, de sorte que la vitesse sera lente.
var arr = arr = new Array(11111111).fill(255);
var benches =
[ [ "empty", () => {
for(var a = 0, l = arr.length; a < l; a++);
}]
, ["for-loop", () => {
for(var a = 0, l = arr.length; a < l; ++a)
var b = arr[a] + 1;
}]
, ["for-loop++", () => {
for(var a = 0, l = arr.length; a < l; a++)
var b = arr[a] + 1;
}]
, ["for-loop - arr.length", () => {
for(var a = 0; a < arr.length; ++a )
var b = arr[a] + 1;
}]
, ["reverse for-loop", () => {
for(var a = arr.length - 1; a >= 0; --a )
var b = arr[a] + 1;
}]
,["while-loop", () => {
var a = 0, l = arr.length;
while( a < l ) {
var b = arr[a] + 1;
++a;
}
}]
, ["reverse-do-while-loop", () => {
var a = arr.length - 1; // CAREFUL
do {
var b = arr[a] + 1;
} while(a--);
}]
, ["forEach", () => {
arr.forEach( a => {
var b = a + 1;
});
}]
, ["for..in (only 3.3%)", () => {
var ar = arr.slice(0,arr.length/33);
for( const a in ar ) {
var b = a + 1;
}
}]
, ["Duff's device", () => {
var i = 0;
var r = arr.length % 8;
var n = (arr.length - r) / 8;
if (r > 0) do {
var b = arr[i++] + 1;
}
while (--r);
if (n > 0) do {
var b = arr[i] + 1;
var c = arr[i+1] + 1;
var d = arr[i+2] + 1;
var e = arr[i+3] + 1;
var f = arr[i+4] + 1;
var g = arr[i+5] + 1;
var h = arr[i+6] + 1;
var k = arr[i+7] + 1;
i = --n >>> 3;
}
while (n);
}]
, ["Duff's device negative", () => {
var r = arr.length % 8;
var n = (arr.length-r) / 8; ///Math.floor(arr.length / 8);
var i = arr.length ; // -1;
while(r){
var b = arr[--i] + 1;
--r;
}
while(n){
var b = arr[i] + 1;
var c = arr[i-1] + 1;
var d = arr[i-2] + 1;
var e = arr[i-3] + 1;
var f = arr[i-4] + 1;
var g = arr[i-5] + 1;
var h = arr[i-6] + 1;
var j = arr[i-7] + 1;
i = --n >>> 3;
}
}]];
function bench(title, f) {
var t0 = performance.now();
var res = f();
return performance.now() - t0; // console.log(`${title} took ${t1-t0} msec`);
}
var globalVarTime = bench( "for-loop without 'var'", () => {
// Here if you forget to put 'var' so variables'll be global
for(a = 0, l = arr.length; a < l; ++a)
var b = arr[a] + 1;
});
var times = benches.map( function(a) {
arr = new Array(11111111).fill(255);
return [a[0], bench(...a)]
}).sort( (a,b) => a[1]-b[1] );
var max = times[times.length-1][1];
times = times.map( a => {a[2] = (a[1]/max)*100; return a; } );
var template = (title, time, n) =>
`<div>` +
`<span>${title} </span>` +
`<span style="width:${3+n/2}%"> ${Number(time.toFixed(3))}msec</span>` +
`</div>`;
var strRes = times.map( t => template(...t) ).join("\n") +
`<br><br>for-loop without 'var' ${globalVarTime} msec.`;
var $container = document.getElementById("container");
$container.innerHTML = strRes;
body { color:#fff; background:#333; font-family:helvetica; }
body > div > div { clear:both }
body > div > div > span {
float:left;
width:43%;
margin:3px 0;
text-align:right;
}
body > div > div > span:nth-child(2) {
text-align:left;
background:darkorange;
animation:showup .37s .111s;
-webkit-animation:showup .37s .111s;
}
@keyframes showup { from { width:0; } }
@-webkit-keyframes showup { from { width:0; } }
<div id="container"> </div>
2014 While
est de retour
Pensez simplement logique.
Regardez ceci
for( var index = 0 , length = array.length ; index < length ; index++ ) {
//do stuff
}
for
a 3 paramètresMaintenant, dites-moi pourquoi cela devrait être plus rapide que:
var length = array.length;
while( --length ) { //or length--
//do stuff
}
while
n'a qu'un paramètreJ'étais totalement dérouté lorsque Chrome 28 a montré que la boucle for est plus rapide que le moment. Cela doit avoir une sorte de
"Euh, tout le monde utilise la boucle for, concentrons-nous là-dessus lorsque vous développez pour Chrome."
Mais maintenant, en 2014, la boucle While est de retour sur Chrome. c'est 2 fois plus rapide, sur les autres/anciens navigateurs, c'était toujours plus rapide.
Dernièrement, j'ai fait de nouveaux tests. Or, dans le monde réel, ces codes abrégés ne valent absolument rien et jsperf ne peut pas exécuter correctement la boucle while, car il faut recréer le tableau array.length, qui prend également du temps.
vous ne pouvez pas obtenir la vitesse réelle d'une boucle while sur jsperf.
vous devez créer votre propre fonction personnalisée et vérifier cela avec window.performance.now()
Et oui ... il n’est pas possible que la boucle while soit simplement plus rapide.
Le vrai problème est en fait la manipulation/le rendu du temps/le temps du dessin ou comment vous voulez l'appeler.
Par exemple, j'ai une scène de toile où j'ai besoin de calculer les coordonnées et les collisions ... cela se fait entre 10-200 MicroSecondes (pas millisecondes). il faut en fait plusieurs millisecondes pour tout restituer. Même chose que dans DOM.
MAIS
Il existe un autre moyen très performant d'utiliser le for loop
dans certains cas ... par exemple pour copier/cloner un tableau
for(
var i = array.length ;
i > 0 ;
arrayCopy[ --i ] = array[ i ] // doing stuff
);
Notez la configuration des paramètres:
Cela dit, cela confirme que des machines comme le -
en écrivant que je pensais le raccourcir un peu, enlever quelques trucs inutiles et écrire celui-ci en utilisant le même style:
for(
var i = array.length ;
i-- ;
arrayCopy[ i ] = array[ i ] // doing stuff
);
Même s'il est plus court, l'utilisation de i
semble une nouvelle fois ralentie. Elle est 1/5 plus lente que la précédente boucle for
et la boucle while
.
Remarque: le ;
est très important après le for looo sans {}
Même si je viens de vous dire que jsperf n’est pas le meilleur moyen de tester des scripts .. j’ai ajouté ces 2 boucles ici
http://jsperf.com/caching-array-length/4
Et voici une autre réponse à propos des performances en javascript
https://stackoverflow.com/a/21353032/24507
Cette réponse montre les méthodes les plus performantes pour écrire du javascript. Donc si vous ne pouvez pas lire cela, demandez et vous obtiendrez une réponse ou lirez un livre sur le javascript http://www.ecma-international.org/ecma-262/5.1/
http://jsperf.com/caching-array-length/6
La dernière révision du test, que j'ai préparée (en réutilisant l'ancienne), montre une chose.
La longueur du cache n’est pas très importante, mais elle ne nuit pas.
Chaque premier passage du test lié ci-dessus (sur l'onglet récemment ouvert) donne les meilleurs résultats pour les 4 derniers extraits (3ème, 5ème, 7ème et 10ème dans les graphiques) en Chrome, Opera et Firefox dans ma Debian Squeeze 64 -bit ( mon matériel de burea ). Les courses suivantes donnent un résultat assez différent.
Les conclusions en termes de performances sont simples:
!==
au lieu de <
. shift()
- sont également efficaces. tl; dr
De nos jours (2011.10), le motif ci-dessous semble être le plus rapide.
for (var i = 0, len = arr.length; i !== len; i++) {
...
}
Notez que la mise en cache de arr.length
n'est pas cruciale ici, vous pouvez donc simplement tester i !== arr.length
et les performances ne baisseront pas, mais votre code sera plus court.
PS: Je sais que dans l'extrait avec shift()
, son résultat pourrait être utilisé au lieu d'accéder à l'élément 0th, mais j'ai oublié de voir qu'après avoir réutilisé la révision précédente (qui avait mal tourné), et plus tard, je ne voulais pas perdre résultats déjà obtenus.
"Best" comme dans la performance pure? ou performance ET lisibilité?
La performance pure "meilleure" est la suivante: elle utilise un cache et l'opérateur de préfixe ++ (mes données: http://jsperf.com/caching-array-length/189 )
for (var i = 0, len = myArray.length; i < len; ++i) {
// blah blah
}
Je dirais que la boucle sans cache pour la boucle est le meilleur équilibre entre le temps d'exécution et le temps de lecture du programmeur. Tous les programmeurs ayant commencé avec C/C++/Java ne perdront pas une ms à lire celui-ci
for(var i=0; i < arr.length; i++){
// blah blah
}
** cache la longueur du tableau à l'intérieur de la boucle, quelques secondes s'écouleront. Dépend des éléments du tableau s'il y a plus d'éléments dans le tableau, il existe une différence majeure en ce qui concerne MS of time *
**
sArr; //Array[158];
for(var i = 0 ; i <sArr.length ; i++) {
callArray(sArr[i]); //function call
}
***end: 6.875ms***
**
**
sArr; //Array[158];
for(var i = 0,len = sArr.length ; i < len ; i++) {
callArray(sArr[i]); //function call
}
***end: 1.354ms***
**
Ceci semble être le moyen le plus rapide de loin ...
var el;
while (el = arr.shift()) {
el *= 2;
}
Prenez en compte que cela va consommer le tableau, le manger et ne rien laisser ...
C'est l'année 2017 .
J'ai fait des tests.
https://jsperf.com/fastest-way-to-iterate-through-an-array/
On dirait que la méthode while
est la plus rapide sur Chrome.
On dirait que le décrément gauche (--i
) est beaucoup plus rapide que les autres (++i
, i--
, i++
) sur Firefox.
Cette approche est le à jeun en moyenne. Mais cela itère le tableau dans l'ordre inverse.
let i = array.length;
while (--i >= 0) {
doSomething(array[i]);
}
Si la commande à terme est importante, utilisez cette approche.
let ii = array.length;
let i = 0;
while (i < ii) {
doSomething(array[i]);
++i;
}
J'écris toujours dans le premier style.
Même si un compilateur est assez intelligent pour l'optimiser pour les tableaux, il l'est tout de même si nous utilisons DOMNodeList ici ou un objet compliqué avec une longueur calculée?
Je sais quelle est la question sur les tableaux, mais je pense que c'est une bonne pratique d'écrire toutes vos boucles dans un style.
var arr = []; // The array
var i = 0;
while (i < arr.length) {
// Do something with arr[i]
i++;
}
i ++ est plus rapide que ++ i, --i et i--
En outre, vous pouvez enregistrer la dernière ligne en faisant arr [i ++] la dernière fois que vous devez accéder à i (mais cela peut être difficile à déboguer).
Vous pouvez le tester ici (avec d’autres tests de boucle): http://jsperf.com/for-vs-whilepop/5
J'ai essayé d'autres manières d'itérer un grand tableau et j'ai découvert que réduire de moitié la longueur du tableau, puis itérer les deux moitiés d'une seule boucle est plus rapide. Cette différence de performance est visible lors du traitement d’énormes tableaux .
var firstHalfLen =0;
var secondHalfLen = 0;
var count2=0;
var searchterm = "face";
var halfLen = arrayLength/2;
if(arrayLength%2==halfLen)
{
firstHalfLen = Math.ceil(halfLen);
secondHalfLen=Math.floor(halfLen);
}
else
{
firstHalfLen=halfLen;
secondHalfLen=halfLen;
}
for(var firstHalfCOunter=0,secondHalfCounter = arrayLength-secondHalfLen;
firstHalfCOunter < firstHalfLen;
firstHalfCOunter++)
{
if(mainArray[firstHalfCOunter].search(new RegExp(searchterm, "i"))> -1)
{
count2+=1;
}
if(secondHalfCounter < arrayLength)
{
if(mainArray[secondHalfCounter].search(new RegExp(searchterm, "i"))> -1)
{
count2+=1;
}
secondHalfCounter++;
}
}
Quelques comparaisons de performances (en utilisant timer.js) entre la longueur mise en cache pour la boucle et la méthode ci-dessus.
La solution la plus élégante que je connaisse consiste à utiliser la carte.
var arr = [1,2,3];
arr.map(function(input){console.log(input);});
La boucle While est un peu plus rapide que pour la boucle.
var len = arr.length;
while (len--) {
// blah blah
}
Utilisez la boucle while à la place
Une boucle while de base est souvent la plus rapide. jsperf.com est un excellent bac à sable pour tester ces types de concepts.
Un autre test de jsperf.com: http://jsperf.com/while-reverse-vs-for-cached-length
La boucle reverse while semble être la plus rapide. Le seul problème est que while (--i) va s'arrêter à 0. Comment puis-je accéder à array [0] dans ma boucle alors?
Depuis septembre 2017 ces tests jsperf affichent le schéma suivant comme étant le plus performant sur Chrome 60:
function foo(x) {
x;
};
arr.forEach(foo);
Est-ce que quelqu'un est capable de se reproduire?
Essaye ça:
var myarray =[],
i = myarray.lenght;
while(i--){
// do somthing
}
Depuis 2019, WebWorker est devenu plus populaire. Pour les grands ensembles de données, nous pouvons utiliser WebWorker pour traiter beaucoup plus rapidement en utilisant pleinement les processeurs multicœurs.
Nous avons également Parallel.js , ce qui rend WebWorker beaucoup plus facile à utiliser pour le traitement des données.