J'ai regardé les "Google Tech Talks". Accélérez votre Javascript et en parlant des boucles, l'orateur mentionne de rester à l'écart des itérations basées sur des fonctions telles que jQuery.each() (entre autres, à environ 24:05 dans la vidéo). Il explique brièvement pourquoi il faut les éviter, ce qui est logique, mais j'avoue ne pas bien comprendre quelle serait l'alternative. Disons que dans le cas où je veux itérer à travers une colonne de cellules de tableau et utiliser la valeur pour manipuler la valeur de la cellule adjacente (juste un exemple rapide). Quelqu'un peut-il expliquer et donner un exemple d'une alternative à l'itération basée sur les fonctions ?
Réponses
Trop de publicités?Il me semble que l'itération basée sur les fonctions serait légèrement plus lente en raison 1) de l'overhead de la fonction elle-même, 2) de l'overhead de la fonction de rappel créée et exécutée N fois, et 3) de la profondeur supplémentaire dans la chaîne de portée. Cependant, j'ai pensé faire un benchmark rapide juste pour le plaisir. Il s'est avéré, au moins dans mon cas de test simple, que l'itération basée sur la fonction était plus rapide. Voici le code et les résultats
Test du code de référence
// Function based iteration method
var forEach = function(_a, callback) {
for ( var _i=0; _i<_a.length; _i++ ) {
callback(_a[_i], _i);
}
}
// Generate a big ass array with numbers 0..N
var a = [], LENGTH = 1024 * 10;
for ( var i=0; i<LENGTH; i++ ) { a.push(i); }
console.log("Array length: %d", LENGTH);
// Test 1: function-based iteration
console.info("function-base iteration");
var end1 = 0, start1 = new Date().getTime();
var sum1 = 0;
forEach(a, function(value, index) { sum1 += value; });
end1 = new Date().getTime();
console.log("Time: %sms; Sum: %d", end1 - start1, sum1);
// Test 2: normal for-loop iteration
console.info("Normal for-loop");
var end2 = 0, start2 = new Date().getTime();
var sum2 = 0;
for (var j=0; j<a.length; j++) { sum2 += a[j]; }
end2 = new Date().getTime();
console.log("Time: %sms; Sum: %d", end2 - start2, sum2);
Chaque test se contente de résumer le tableau, ce qui est simpliste, mais qui peut être vu de manière réaliste dans une sorte de scénario de la vie réelle.
Résultats pour FF 3.5
Array length: 10240
function-base iteration
Time: 9ms; Sum: 52423680
Normal for-loop
Time: 22ms; Sum: 52423680
Il s'avère qu'une base for
l'itération était plus rapide dans ce cas de test. Je n'ai pas encore regardé la vidéo, mais je vais y jeter un coup d'œil et voir s'il y a une différence qui rendrait les itérations basées sur les fonctions plus lentes.
Edit : Ceci n'est en aucun cas la finalité et n'est que les résultats d'un moteur et d'un cas de test. Je m'attendais à ce que les résultats soient inversés (l'itération basée sur les fonctions étant plus lente), mais il est intéressant de voir comment certains navigateurs ont fait des optimisations (qui peuvent ou non être spécifiquement destinées à ce style de JavaScript) pour que le contraire soit vrai.
Si l'ordre de bouclage n'a pas d'importance, ce qui suit devrait être le plus rapide car vous n'avez besoin que d'une seule variable locale ; de plus, la décrémentation du compteur et le contrôle des limites sont effectués avec une seule instruction :
var i = foo.length;
if(i) do { // check for i != 0
// do stuff with `foo[i]`
} while(--i);
Ce que j'utilise normalement est le suivant :
for(var i = foo.length; i--; ) {
// do stuff with `foo[i]`
}
Elle est potentiellement plus lente que la version précédente (post-décrémentation vs pré-décrémentation, for
vs while
), mais plus lisible.