Maison > interface Web > js tutoriel > Exploration approfondie des problèmes d'efficacité et d'optimisation associée des boucles for dans les compétences JavaScript_javascript

Exploration approfondie des problèmes d'efficacité et d'optimisation associée des boucles for dans les compétences JavaScript_javascript

WBOY
Libérer: 2016-05-16 15:10:52
original
1605 Les gens l'ont consulté

Bibliothèque Underscore.js

Combien de boucles avez-vous écrites en une journée (semaine) ?

var i;
for(i = 0; i < someArray.length; i++) {
 var someThing = someArray[i];
 doSomeWorkOn(someThing);
}

Copier après la connexion

C'est inoffensif, bien sûr, mais c'est moche et bizarre et il n'y a pas vraiment de quoi se plaindre. Mais cette façon d’écrire est trop banale.

var i,
 j;
for(i = 0; i < someArray.length; i++) {
 var someThing = someArray[i];
 for(j = 0; j < someThing.stuff.length; j++) {
   doSomeWorkOn(someThing.stuff[j]);
 }
}

Copier après la connexion

Vous étendez du mauvais code, et avant de lancer un tas de si, vous êtes déjà fou.
Je n'ai pas écrit de boucle depuis deux ans.
"De quoi tu parles ?"
C'est vrai, une mauvaise blague. En fait, pas aucun (ok, j’en ai écrit quelques-uns), car je n’écris pas de boucles et mon code est plus facile à comprendre.
Comment?

_.each(someArray, function(someThing) {
 doSomeWorkOn(someThing);
})

Copier après la connexion

Ou mieux encore :

_.each(someArray, doSomeWorkOn);

Copier après la connexion

C'est ce que fait underscorejs. Propre, simple, lisible, court, pas de variables intermédiaires, pas de tonnes de points-virgules, simple et très élégant.
Voici quelques exemples supplémentaires.

var i,
 result = [];
for(i = 0; i < someArray.length; i++) {
 var someThing = someArray[i];
 // 打到这,我已经手疼了
 if(someThing.isAwesome === true) {
   result.push(someArray[i]);
 }
}

Copier après la connexion

Encore une fois, un cas d'utilisation typique pour perdre du temps à utiliser des boucles. Même si ces sites font la promotion de la lutte contre le tabac et du végétarisme, je me sens indigné lorsque je vois ces codes. Regardez la manière simple de l’écrire.

var result = _.filter(someArray, function(someThing) {
 return someThing.isAwesome === true;
})

Copier après la connexion

Comme le nom du filtre en trait de soulignement, seulement 3 lignes de code peuvent vous donner un nouveau tableau.
Ou souhaitez-vous convertir ces tableaux sous une autre forme ?

var result = _.map(someArray, function(someThing) {
 return trasformTheThing(someThing);
})

Copier après la connexion

Les trois exemples ci-dessus sont suffisants dans la vie quotidienne, mais ces fonctions ne suffisent pas pour que le soulignement soit mis sur la table.

var grandTotal = 0,
 somePercentage = 1.07,
 severalNumbers = [33, 54, 42],
 i; // don't forget to hoist those indices;
for(i = 0; i < severalNumbers.length; i++) {
 var aNumber = severalNumbers[i];
 grandTotal += aNumber * somePercentage;
}

Copier après la connexion

version soulignée

var somePercentage = 1.07,
 severalNumbers = [33, 54, 42],
 grandTotal;
grandTotal = _.reduce(severalNumbers, function(runningTotal, aNumber) {
 return runningTotal + (aNumber * somePercentage);
}, 0)

Copier après la connexion

Cela peut sembler un peu étrange au début. J'ai vérifié la documentation sur la réduction et découvert son existence. Puisque je refuse d'utiliser des boucles, c'est mon premier choix. Les éléments ci-dessus ne sont qu'une introduction. La bibliothèque underscorejs possède également de nombreuses fonctions impressionnantes.

Défi de cycle sans utilisation de 30 jours.

N'utilisez aucune boucle pendant les 30 prochains jours. Si vous voyez un tas de choses désagréables et grossières, remplacez-les par chacune ou par une carte. Utilisez un peu plus de réduction.

Vous devez noter que Underscore est la passerelle vers la programmation fonctionnelle. Une manière visible et invisible. Une bonne voie à suivre.


Note OurJS* Les navigateurs modernes prennent actuellement en charge chacune des méthodes de filtrage, de mappage et de réduction, mais la bibliothèque de traits de soulignement peut atteindre la compatibilité avec les anciennes versions d'IE. Voici un exemple écrit à l'aide des méthodes natives ES5 :

.
[3,4,5,3,3].forEach(function(obj){
  console.log(obj);
});

[1,2,3,4,5].filter(function(obj){
  return obj < 3
});

[9,8,5,2,3,4,5].map(function(obj){
  return obj + 2;
});

[1,2,3,4,5].reduce(function(pre, cur, idx, arr) {
  console.log(idx);  //4 个循环: 2-5
  return pre + cur;
});  //15

//sort方法同样很有用
[9,8,5,2,3,4,5].sort(function(obj1, obj2){
  return obj1 - obj2;
});

Copier après la connexion

for in et for boucle

Quelqu'un a souligné que l'efficacité de for in est bien inférieure à celle de for loop. Testons maintenant l'efficacité de l'utilisation de for in, for loop et forEach dans différents navigateurs lors du traitement de grands tableaux.

À l'heure actuelle, la plupart des logiciels open source mettront en cache la longueur du tableau dans la boucle for, car l'opinion courante est que certains navigateurs Array.length recalculeront la longueur du tableau à chaque fois, donc des variables temporaires sont généralement utilisées pour stocker la longueur du tableau. à l'avance, comme :

for (var idx = 0, len = testArray.length; idx < len; idx++) {
 //do sth.
}
Copier après la connexion
Copier après la connexion

Nous testerons également la différence de performances entre la mise en cache et l'absence de mise en cache.

Ajoutez également une opération de sommation dans chaque boucle de test pour montrer qu'il ne s'agit pas d'une boucle vide.

for (var idx = 0, len = testArray.length; idx < len; idx++) {
 //do sth.
}
Copier après la connexion
Copier après la connexion

Nous testerons également la différence de performances entre la mise en cache et l'absence de mise en cache.

Ajoutez également une opération de sommation dans chaque boucle de test pour montrer qu'il ne s'agit pas d'une boucle vide.

Le code de test est le suivant, cliquez sur Exécuter pour voir
Code HTML

<h4 id="browser"></h4>
<table id="results" class="table"></table>
Copier après la connexion

Code JavaScript

function () {

 //准备测试数据, 有200万条数据的大数组
 var testArray = []
  , testObject = {}
  , idx
  , len = 2000000
  , tmp = 0
  , $results = $("#results")
  , $browser = $("#browser")
  ;

 $browser.html(navigator.userAgent);
 $results.html('');

 for (var i = 0; i < len; i++) {
  var number = Math.random(); //若希望加快运算速度可使用取整:Math.random() * 10 | 0
  testArray.push(number);
  testObject[i] = number;
 }

 $results.append('<tr><th>测试代码</th><th>计算结果</th><th>所需时间,毫秒</th></tr>');

 //测试函数
 var test = function(testFunc) {
  var startTime
   , endTime
   , result
   ;

  startTime = new Date();
  tmp = 0;
  testFunc();
  endTime  = new Date();

  //计算测试用例(Test Case)运行所需要的时间
  result = endTime - startTime;
  $results.append('<tr><td><pre class="brush:php;toolbar:false">{0}
{1}{2}'.format(testFunc.toString(), tmp | 0, result)); }; test(function() { //测试for in 的效率 for (idx in testArray) { tmp += testArray[idx]; //经测试,idx是string类型,可能是慢的原因之一 } }); test(function() { //测试for loop循环的效率 for (idx = 0, len = testArray.length; idx < len; idx++) { tmp += testArray[idx]; } }); test(function() { //测试forEach的效率 testArray.forEach(function(data) { tmp += data; }); }); test(function() { //测试不缓存Array.length时效率 for (idx = 0; idx < testArray.length; idx++) { tmp += testArray[idx]; } }); test(function() { //测试使用{} (Object) 存健值对时,使用for in的效率如何 for (idx in testObject) { tmp += testObject[idx]; } }); test(function() { //测试从{} Object查值时的效率如何(这里的健key值事先己知) for (idx = 0, len = testArray.length; idx < len; idx++) { tmp += testObject[idx]; } }); }
Copier après la connexion

Exécuter [Veuillez patienter un instant]
Résultats des tests
Les résultats des tests peuvent varier en fonction du calcul. Ceci est un résumé des résultats des tests de Firefox, Chrome et IE exécutés sur ma machine.

2016313110044207.jpg (971×678)

Voici plusieurs conclusions observées

  • For in est beaucoup plus lent que la boucle for, au moins 20 fois plus lente dans Chrome
  • FF a optimisé forEach (ES5), et ses performances sont meilleures que celles de la boucle for, mais les performances de Chrome/IEn sont médiocres
  • La mise en cache FF/Chrome d'Array.length est un peu plus lente que son utilisation directe. À l'exception de la dernière version d'IE, l'amélioration des performances est minime (c'est très inattendu)
  • Dans certains cas, les performances du moteur JS du FF semblent meilleures que celles du V8
Étiquettes associées:
source:php.cn
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal