Javascript: la méthode de longueur est-elle efficace?

Je fais un certain codage javascript et je me demandais si la méthode de la longueur est "précomputed", ou rappelé par le moteur JS.

La question est donc la suivante:

Si je vérifie très souvent une longueur de tableau, et en supposant que je ne le modifie pas (le rendant immuable par une fermeture), devrais-je précomputer la méthode de la longueur et la stocker dans une variable?

Merci!

Tous les interprètes majeurs fournissent des accesseurs efficaces pour les longueurs de tableaux natifs, mais pas pour des objets similaires à des NodeList comme NodeList s.

"Bouclage efficace en Javascript"

 Test / Browser Firefox 2.0 Opera 9.1 Internet Explorer 6 Native For-Loop 155 (ms) 121 (ms) 160 (ms) ... Improved Native While-Loop 120 (ms) 100 (ms) 110 (ms) 

"Code JavaScript efficace" suggère

 for( var i = 0; i < document.getElementsByTagName('tr').length; i++ ) { document.getElementsByTagName('tr')[i].className = 'newclass'; document.getElementsByTagName('tr')[i].style.color = 'red'; ... } 

 var rows = document.getElementsByTagName('tr'); for( var i = 0; i < rows.length; i++ ) { rows[i].className = 'newclass'; rows[i].style.color = 'red'; ... } 

Aucun de ces éléments n'est efficace. getElementsByTagName renvoie un objet dynamique, pas un tableau statique. Chaque fois que la condition de la boucle est cochée, Opera doit réévaluer l'objet et déterminer le nombre d'éléments qu'il renvoie pour déterminer la propriété de la length . Cela prend un peu plus de temps que de vérifier contre un nombre statique.

Comme toujours, la réponse est "cela dépend".

Testeons les tableaux natifs avec un tableau d'éléments de million d'éléments:

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

http://josh3736.net/images/arrlen.png

Chrome et Firefox optimisent l'accessoire de propriété pour être aussi efficace que la copie de la longueur à une variable locale. IE et Opera ne sont pas, et sont 50% + plus lents.

Toutefois , gardez à l'esprit que les résultats de test «ops / second» désignent le nombre d' itérations complètes à travers un tableau d'un million d'éléments par seconde.

Pour mettre cela en perspective, même dans IE8 (le pire des artistes de ce groupe) – qui a marqué 44 et 3.9 sur l'accès à la propriété et la variable locale (respectivement) – la pénalité par itération était de 2 μs insuffisante. Iterant plus d'un millier d'éléments, en utilisant array.length ne vous coûtera que 2 ms supplémentaires. En d'autres termes: méfiezvous de l'optimisation prématurée .

La longueur d'un tableau réel n'est pas calculée à la volée. Il est stocké dans le cadre de la structure de données du tableau afin d'y accéder ne nécessite plus de travail que d'obtenir la valeur (il n'y a pas de calcul). En tant que tel, il sera généralement aussi rapide que de récupérer toute propriété fixe d'un objet. Comme vous pouvez le voir dans ce test de performance, il n'y a absolument aucune différence entre la récupération de la longueur d'un tableau et la récupération d'une propriété d'un objet:

http://jsperf.com/length-comparisons

Une exception à cela est que les objets nodeList que le DOM revient de fonctions comme getElementsByTagName() ou getElementsByClassName() . Dans ces derniers, il est souvent beaucoup plus lent d'accéder à la propriété length. C'est probablement parce que ces objets nodeList ne sont pas des objets javascript fidèles et il peut y avoir un pont entre Javascript et le code natif qui doit être traversé chaque fois que quelque chose est accessible à partir de ces objets. Dans ce cas, il serait beaucoup plus rapide (10-100 fois plus rapide) de mettre en cache la longueur dans une variable locale plutôt que de l'utiliser à plusieurs reprises dans une boucle hors de nodeList. Je l'ai ajouté à la comparaison de longueur et vous pouvez voir combien il est plus lent.

Dans certains navigateurs, il est significativement plus rapide de mettre la longueur dans une variable locale et de l'utiliser à partir de là, si vous en faites référence encore et encore (comme dans une boucle). Voici le graphique de performances du test jsperf ci-dessus:

Il existe probablement une augmentation de vitesse modeste pouvant être atteinte en mettant en cache la longueur dans une variable locale en raison de la vitesse de recherche d'attribut. Cela peut ou non être négligeable, selon la manière dont le moteur JS JIT est le code.

Voir http://jsperf.com/for-loop-caching pour un test de JSperf rudimentaire.

Pour tout objet de type collection dont vous ne manipulerez pas la longueur (p. Ex. Toute collection immuable), il est toujours recommandé de mettre en mémoire cache sa longueur pour de meilleures performances.

 var elems = document.getElementsByName("tst"); var elemsLen = elems.length; var i; for(i = 0; i < elemsLen; ++i) { // work with elems... example: // elems[i].selected = false; } elems = [10,20,30,40,50,60,70,80,90,100]; elemsLen = elems.length; for(i = 0; i < elemsLen; ++i) { // work with elems... example: // elems[i] = elems[i] / 10; }