1. Déclaration de boucle
Comme nous le savons tous, les instructions de boucle couramment utilisées incluent for, while, do-while, for-in et forEach. Sauf que les performances de for-in et forEach sont légèrement inférieures, notre choix des trois premiers se base généralement davantage sur les besoins que sur des considérations de performances. Aujourd'hui, nous allons tester leurs performances respectives et nous dire qu'ils peuvent toujours fonctionner dans les conditions les plus extrêmes. cas. Quelles optimisations peuvent être effectuées.
Tout d’abord, parlons des raisons pour lesquelles for-in et forEach sont plus lents que les autres. for-in est généralement utilisé pour parcourir les noms d'attributs d'objet. Étant donné que chaque opération d'itération recherche simultanément les attributs de l'instance elle-même et les attributs de la chaîne de prototypes, l'efficacité est définitivement faible alors que forEach est une itération basée sur une fonction ; (une attention particulière est requise) Cependant, toutes les versions d'IE ne le prennent pas en charge. Si nécessaire, vous pouvez utiliser des bibliothèques telles que JQuery.) La surcharge causée par l'appel de méthodes externes pour chaque élément du tableau est la principale raison de la lenteur.
Ensuite, regardons ce que faire, pendant et pendant que faire à chaque itération.
var length = items.length; for(var i = 0; i < length; i++) process(items[i]); var j = 0; while(j < length) process(items[j++]); var k = 0; do { process(items[k++]); } while(k < length);
Dans chaque boucle ci-dessus, cette opération se produira à chaque fois que le corps de la boucle sera exécuté :
Nous pouvons améliorer les performances de la boucle en inversant l'ordre du tableau :
for(var i = items.length; i--; ) process(items[i]); var j = items.length; while(j--) process(items[j]); var k = items.length - 1; do { process(items[k]); } while(k--);
Dans cet exemple, une boucle d'ordre inverse est utilisée et l'opération de soustraction est intégrée dans la condition de boucle. Désormais, chaque condition de contrôle est simplement comparée à 0. La condition de contrôle est comparée à une valeur vraie. Tout nombre non nul est automatiquement converti en vrai, tandis qu'une valeur nulle équivaut à faux. En effet, la condition de contrôle passe de deux comparaisons (Le nombre d'itérations est-il inférieur au total ? Est-ce vrai ?) à une seule comparaison (Est-ce vrai ?). Ceci est réduit de deux comparaisons à une par itération, améliorant encore la vitesse de boucle.
Test de performances :
Alors est-ce vraiment le cas ? L'argent réel n'a pas peur de la vérification du navigateur. Le code du test est très simple, encapsulant 8 fonctions pour 8 situations différentes (les informations sur les profils ne peuvent pas être imprimées dans Firefox sans minuterie, la raison est inconnue) :
// init array var a = []; var length = 10; for(var i = 0; i < length; i++) a[i] = 1; function for_in() { var sum = 0; for(var i in a) sum += a[i]; } function for_each() { var sum = 0; a.forEach(function(value, index, array) { sum += value; }); } function for_normal() { var sum = 0; for(var i = 0; i < length; i++) sum += a[i]; } function for_reverse() { var sum = 0; for(var i = length; i--; ) sum += a[i]; } function while_normal() { var sum = 0; var i = 0; while(i < length) sum += a[i++]; } function while_reverse() { var sum = 0; var i = length; while(i--) sum += a[i]; } function do_while_normal() { var sum = 0; var i = 0; do { sum += a[i++]; } while(i < length); } function do_while_reverse() { var sum = 0; var i = length - 1; do { sum += a[i]; } while(i--); } setTimeout(function() { console.profile(); for_in(); for_each(); for_normal(); for_reverse(); while_normal(); while_reverse(); do_while_normal(); do_while_reverse(); console.profileEnd(); }, 1000);
Lorsque la longueur du tableau est de 100, nous avons constaté que les résultats sous Firefox sont effectivement similaires aux attentes : for-each et for-in sont inefficaces, et l'ordre inverse est légèrement plus efficace que l'ordre direct. (Les profils sous chrome ne s'affichent pas car le temps est trop court)
Lorsque le volume de données atteint 1 million, les résultats sous Firefox et Chrome sont comme prévu, mais il existe de légères différences. Les performances de for-in sous ff sont meilleures que celles de for-each, mais les performances de for-in sous chrome sont médiocres et un avertissement est directement émis. Bien que les performances de l'itération inverse soient légèrement améliorées, l'amélioration n'est pas grande et la lisibilité du code est réduite.
Résumé :
2. Déclarations conditionnelles
Les instructions conditionnelles courantes incluent if-else et switch-case. Alors, quand utiliser if-else et quand utiliser l'instruction switch-case ?
Regardons d'abord le code d'une simple instruction if-else :
if (value == 0){ return result0; } else if (value == 1){ return result1; } else if (value == 2){ return result2; } else if (value == 3){ return result3; } else if (value == 4){ return result4; } else if (value == 5){ return result5; } else if (value == 6){ return result6; } else if (value == 7){ return result7; } else if (value == 8){ return result8; } else if (value == 9){ return result9; } else { return result10; }
Dans le pire des cas (valeur=10), nous devrons peut-être faire 10 jugements avant de renvoyer le résultat correct. Alors, comment optimiser ce code ? Une stratégie d’optimisation évidente consiste à juger à l’avance la valeur la plus probable. Par exemple, la valeur est la plus susceptible d’être égale à 5 ou 10, puis à faire ces deux jugements à l’avance. Mais généralement, nous ne le savons pas (le choix le plus probable). Dans ce cas, nous pouvons adopter une stratégie de recherche par arbre binaire pour optimiser les performances.
if (value < 6){ if (value < 3){ if (value == 0){ return result0; } else if (value == 1){ return result1; } else { return result2; } } else { if (value == 3){ return result3; } else if (value == 4){ return result4; } else { return result5; } } } else { if (value < 8){ if (value == 6){ return result6; } else { return result7; } } else { if (value == 8){ return result8; } else if (value == 9){ return result9; } else { return result10; } } }
这样优化后我们最多进行4次判断即可,大大提高了代码的性能。这样的优化思想有点类似二分查找,和二分查找相似的是,只有value值是连续的数字时才能进行这样的优化。但是代码这样写的话不利于维护,如果要增加一个条件,或者多个条件,就要重写很多代码,这时switch-case语句就有了用武之地。
将以上代码用switch-case语句重写:
switch(value){ case 0: return result0; case 1: return result1; case 2: return result2; case 3: return result3; case 4: return result4; case 5: return result5; case 6: return result6; case 7: return result7; case 8: return result8; case 9: return result9; default: return result10; }
swtich-case语句让代码显得可读性更强,而且swtich-case语句还有一个好处是如果多个value值返回同一个结果,就不用重写return那部分的代码。一般来说,当case数达到一定数量时,swtich-case语句的效率是比if-else高的,因为switch-case采用了branch table(分支表)索引来进行优化,当然各浏览器的优化程度也不一样。
除了if-else和swtich-case外,我们还可以采用查找表。
var results = [result0, result1, result2, result3, result4, result5, result6, result7, result8, result9, result10]; //return the correct result return results[value];
当数据量很大的时候,查找表的效率通常要比if-else语句和swtich-case语句高,查找表能用数字和字符串作为索引,而如果是字符串的情况下,最好用对象来代替数组。当然查找表的使用是有局限性的,每个case对应的结果只能是一个取值而不能是一系列的操作。
小结:
以上就是本文的全部内容,希望对大家的学习有所帮助。