J'ai regardé les discussions techniques de Google Speed Up Your Javascript et en parlant de boucles, le locuteur mentionne de rester loin des itérations basées sur la fonction telles que jQuery.each() (entre autres, vers 24:05 dans la vidéo). Il explique brièvement pourquoi les éviter, ce qui est logique, mais je ne comprends pas très bien quelle serait une alternative. Dites, dans le cas où je veux parcourir 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'alternative à l'itération basée sur la fonction?Alternatives à l'itération basée sur la fonction javascript (par exemple jQuery.each())
Répondre
Juste une simple boucle devrait être plus rapide si vous avez besoin de boucle.
var l = collection.length;
for (var i = 0; i<l; i++) {
//do stuff
}
Mais, juste parce qu'il est plus rapide ne signifie pas qu'il est toujours important qu'il en est ainsi.
Cela s'exécute sur le client, pas sur le serveur, vous n'avez donc pas besoin de vous soucier de la mise à l'échelle avec le nombre d'utilisateurs, et s'il est rapide avec .each(), laissez-le. Mais, si c'est lent, une boucle for pourrait l'accélérer.
Ye olde boucle for
Il me semble que ce serait le cas cette itération par fonction serait légèrement plus lent en raison de la 1) les frais généraux de la fonction elle-même, 2) les frais généraux de la fonction de rappel étant créé et exécuté N fois, et 3) la profondeur supplémentaire dans la chaîne de portée. Cependant, je pensais que je ferais une référence rapide juste pour les coups de pied. Il s'avère, 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
Code de référence Test
// 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 résume tout le tableau qui est simpliste, mais quelque chose qui peut être vu de manière réaliste dans une sorte de scénario de la vie réelle.
Résultats pour 3,5 FF
Array length: 10240
function-base iteration
Time: 9ms; Sum: 52423680
Normal for-loop
Time: 22ms; Sum: 52423680
avère qu'une itération for
de base a été 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 diffère quelque part qui rendrait les itérations basées sur les fonctions plus lentes. Edit: Ce n'est en aucun cas le résultat final, c'est-à-dire tous les résultats d'un seul moteur et d'un seul cas d'essai. 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 cibler spécifiquement ce style de JavaScript) afin que le l'opposé est vrai.
C'est parce que vous avez utilisé "j
Je suis pleinement conscient de cette optimisation; cependant, il ne devrait pas avoir d'influence sur ce test car vous remarquerez que les deux boucles 'for' ont une structure et un manque d'optimisation identiques. Mais, comme le premier test a montré des résultats inattendus, je vais l'exécuter à nouveau avec cette optimisation pour voir si cela change quelque chose, mais je ne suis pas convaincu à ce point que ça le fera. Les deux itérations devraient diminuer d'un montant similaire. –
@chad Comme je le soupçonnais, cette optimisation n'a pas changé les résultats des tests de manière significative. En fait, je considérerais cela comme une fausse optimisation avec cette structure de données. Pour les structures de données en direct (comme les conteneurs Dom), cette optimisation est utile. –
Si l'ordre de bouclage n'a pas d'importance, les éléments suivants doivent être les plus rapides car vous n'avez besoin que d'une seule variable locale; aussi, décrémenter le compteur et les limites vérification sont faites 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 la suivante:
for(var i = foo.length; i--;) {
// do stuff with `foo[i]`
}
Il est potentiellement plus lente que la version précédente (post-vs pré -decrement, for
vs while
), mais plus lisible.
La méthode la plus rapide pour itérer consiste à réduire les tâches que vous effectuez dans la boucle. Faites sortir les éléments de l'itération et minimisez les recherches/incréments dans la boucle, par ex.
var i = arr.length;
while (i--) {
console.log("Item no "+i+" is "+arr[i]);
}
NB! En testant sur la dernière version de Safari (avec WebKit nightly), Chrome et Firefox, vous remarquerez que peu importe le type de boucle que vous choisissez si ce n'est pas for each
ou for in
(ou pire, toutes les fonctions dérivées construites sur eux).
De plus, ce qui se révèle, est que la boucle for
suivante est très légèrement plus vite que l'option ci-dessus:
var l = arr.length;
for (var i=l; i--;) {
console.log("Item no "+i+" is "+arr[i]);
}
- 1. fonction d'appel basée sur le changement dom
- 2. Javascript clientHauteur et alternatives
- 3. Alternatives à la fonction d'en-tête de PHP
- 4. Application de carte interactive basée sur Javascript
- 5. passer plusieurs arguments par Eval à la fonction Javascript
- 6. NHibernate Recherche par exemple
- 7. validation basée sur l'annotation basée sur le haricot
- 8. Alternatives de JSON.stringify() en JavaScript
- 9. Structure de fichier pour une application Web basée sur javascript
- 10. Alternatives à YQL
- 11. exemple de fonction pour sortedArrayUsingFunction à Cocoa
- 12. application basée sur la localisation
- 13. Est-ce que Vim a une fonction de commentaire automatique basée sur la syntaxe du fichier?
- 14. Alternatives à popen/pclose?
- 15. Évaluation basée sur la colonne correspondant à une chaîne
- 16. Publication basée sur la date ASP.NET MVC
- 17. Différence entre la réflexion ComponentModel (par exemple PropertyDescriptor) et la réflexion standard (par exemple PropertyInfo)?
- 18. détection d'un objet sur l'image basée sur la forme géométrique
- 19. Alternatives à WCF
- 20. Javascript moquerie cadre - exemple Jack
- 21. NoSQL - Alternatives à SGBDR
- 22. Comment obtenir un élément spécifique dans la boucle jQuery.each
- 23. Chaîne de connexion dynamique basée sur la variable de session
- 24. Alternatives légères à NHibernate
- 25. Comment ajouter la taille de texte par défaut Fonction - Javascript
- 26. Alternatives à TOAD (Linux)
- 27. Optimisation des alternatives à DateTime.Now
- 28. Progression basée sur la console en Java
- 29. Alternatives à window.scrollMaxY?
- 30. Application implémentant la fonction d'accélération (exemple de code) pour l'iPhone
La voie de jeûne du itérer en javascript est do { // code être exécuté } while (--currentIndex) Bien sûr, vous ne pouvez l'utiliser que lorsque l'ordre n'est pas important (ou que l'ordre inverse est souhaitable) – klaaspieter
J'utilise normalement 'for (var i = foo.length; i-- ;) {} '; une boucle 'do..while' avec pré-décrémentation pourrait être plus rapide, mais en pratique la différence compte rarement – Christoph
@klaaspieter, vous pouvez simplement inverser l'ordre en utilisant ++ currentIndex et, avant le bloc, faire currentIndex * = -1 ; – Dykam