Maison > interface Web > js tutoriel > le corps du texte

Conseils pour améliorer les performances des programmes JavaScript à l'aide du tableau de paramètres des conseils Function.apply()_javascript

WBOY
Libérer: 2016-05-16 15:24:00
original
1332 Les gens l'ont consulté

Parlons des compétences de Function.apply() pour améliorer les performances du programme.

Commençons par la fonction Math.max(). Math.max peut être suivi de n'importe quel nombre de paramètres, et renvoie enfin la valeur maximale parmi tous les paramètres.

Par exemple

alert(Math.max(5,8))  //8 
alert(Math.max(5,7,9,3,1,6))  //9 
Copier après la connexion

Mais dans de nombreux cas, nous devons trouver le plus grand élément du tableau.

var arr=[5,7,9,1] 
alert(Math.max(arr))  //  这样却是不行的。一定要这样写 
function getMax(arr){ 
  var arrLen=arr.length; 
  for(var i=0,ret=arr[0];i<arrLen;i++){ 
    ret=Math.max(ret,arr[i]);     
  } 
  return ret; 
}  
Copier après la connexion

Écrire ainsi est fastidieux et inefficace. Si vous utilisez apply, regardez le code :

function getMax2(arr){ 
  return Math.max.apply(null,arr) 
} 
Copier après la connexion

Les deux morceaux de code atteignent le même objectif, mais getMax2 est beaucoup plus élégant, efficace et concis.

Regardez le test de performance :

Test de performances getMax

var myArr=new Array() 
function fillRnd(arrLen){ //填入 arrLen个1-10的随机数字到数组 
  for(var i=0,arr=[];i<arrLen;i++){ 
    arr[i]=Math.ceil(Math.random()*10) 
  } 
  return arr 
} 
function getMax(arr){ 
  var arrLen=arr.length; 
  for(var i=0,ret=arr[0];i<arrLen;i++){ 
    ret=Math.max(ret,arr[i]);     
  } 
  return ret; 
} 
function getMax2(arr){ 
  return Math.max.apply(null,arr) 
} 
myArr=fillRnd(20*10000) //生成20万个随机数填到数组 
var t1=new Date() 
var max1=getMax(myArr) 
var t2=new Date() 
var max2=getMax2(myArr) 
var t3=new Date() 
if (max1!==max2) alert("error") 
alert([t3-t2,t2-t1])  //在我机器上 96,464 .不同的机器,结果可能有差异 
Copier après la connexion

En comparant 200 000 données, le temps getMax2 est de 96 ms et le temps getmax est de 464. La différence entre les deux est de 5 fois

Un autre exemple est la méthode push d'un tableau.

var arr1=[1,3,4]; 
var arr2=[3,4,5];
Copier après la connexion

Si nous voulons développer arr2, puis ajouter à arr1 un par un, enfin laissez arr1=[1,3,4,3,4,5]

arr1.push(arr2) ne fonctionne évidemment pas. Parce que faire cela obtiendra [1,3,4, [3,4,5] ]

On ne peut utiliser qu'une boucle pour pousser un par un (bien sûr vous pouvez aussi utiliser arr1.concat(arr2) mais la méthode concat ne change pas arr1 elle-même)

var arrLen=arr2.length 
for(var i=0;i<arrLen;i++){ 
  arr1.push(arr2[i]) 
}
Copier après la connexion

Depuis que nous avons Apply, les choses sont devenues si simples

Array.prototype.push.apply(arr1,arr2) 
Copier après la connexion

Pièce jointe : Comment optimiser les performances des scripts JavaScript

Avec le développement d'Internet et l'amélioration de la vitesse du réseau et de la vitesse des machines, de plus en plus de sites Web utilisent une technologie client riche. Ajax est désormais la méthode la plus populaire. JavaScript est un langage interprété, donc s'il peut atteindre le même niveau que C/Java, cela limite ce qu'il peut faire sur le client. Afin d'améliorer ses performances, je souhaite m'appuyer sur ce que j'ai fait pour JavaScript auparavant. parler de ma propre expérience, dans l'espoir d'aider tout le monde à améliorer les performances de ses scripts JavaScript.

Niveau de langue

Boucle

La boucle est une structure de contrôle très couramment utilisée. La plupart des choses en dépendent pour se terminer. En JavaScript, nous pouvons utiliser trois types de boucles : for(;;), while() et for(in). this L'efficacité de for(in) parmi les trois types de boucles est extrêmement faible car elle doit interroger la clé de hachage, elle doit donc être utilisée le moins possible si possible. Les performances des boucles for(;;) et while doivent être considérées comme fondamentalement équivalentes (lorsqu'elles sont utilisées au quotidien).

En fait, la façon d'utiliser ces deux boucles est très particulière. J'ai eu des situations intéressantes lors de mes tests, voir l'annexe. La conclusion finale est :

Si la variable de boucle incrémente ou décrémente, n'attribuez pas de valeur à la variable de boucle seule. Vous devez utiliser l'opérateur imbriqué ou - lors de sa dernière lecture.

Si vous souhaitez comparer avec la longueur du tableau, vous devez au préalable placer l'attribut de longueur du tableau dans une variable locale pour réduire le nombre de requêtes.

Variables locales et variables globales

Les variables locales sont accessibles plus rapidement que les variables globales, car les variables globales sont en fait membres de l'objet global, tandis que les variables locales sont placées sur la pile de la fonction.

Ne pas utiliser Eval

Utiliser eval équivaut à appeler à nouveau le moteur d'interprétation pour exécuter le contenu au moment de l'exécution, ce qui prend beaucoup de temps. À l'heure actuelle, les modèles de fonctions peuvent être implémentés à l'aide de fermetures prises en charge par JavaScript (pour plus de détails sur les fermetures, veuillez vous référer au contenu pertinent sur la programmation fonctionnelle)

Réduire la recherche d'objets

En raison de l'interprétabilité de JavaScript, a.b.c.d.e nécessite au moins 4 opérations de requête. Vérifiez d'abord a, puis vérifiez b dans a, puis vérifiez c dans b, et ainsi de suite. Par conséquent, si de telles expressions apparaissent à plusieurs reprises, ces expressions doivent rester aussi rares que possible. Vous pouvez utiliser des variables locales pour les placer dans un emplacement temporaire pour l'interrogation.

Cela peut être combiné avec le bouclage, car nous avons souvent besoin de boucler en fonction de la longueur des chaînes et des tableaux, et généralement cette longueur reste inchangée. Par exemple, chaque fois que a.length est interrogé, une opération supplémentaire est requise, et. Si vous définissez var len=a.length à l'avance, il y aura une requête de moins.

Concaténation de chaînes

Si vous ajoutez une chaîne, il est préférable d'utiliser l'opération s =anotherStr au lieu d'utiliser s=s anotherStr.

Si vous souhaitez concaténer plusieurs chaînes, vous devez utiliser less =, tel que

s =a;s =b;s =c; doit être écrit comme
s =a b c; et si vous collectez des chaînes, par exemple en effectuant plusieurs opérations = sur la même chaîne, il est préférable d'utiliser un cache. Comment l'utiliser ? Utilisez des tableaux JavaScript pour collecter, et enfin utilisez la méthode join pour vous connecter, comme suit

var buf = new Array();for(var i = 0; i < 100; i++){ buf.push(i.toString());}var all = buf.join("");类型转换
Copier après la connexion

La conversion de type est une erreur courante que tout le monde commet, car JavaScript est un langage typé dynamiquement et vous ne pouvez pas spécifier le type d'une variable.

1. Convertissez les nombres en chaînes et utilisez "" 1. Même si cela semble un peu moche, c'est en fait le plus efficace, en termes de performances :
("" ) > String() > .toString() >

Ceci est en fait quelque peu similaire à la "quantité directe" ci-dessous. Essayez d'utiliser les opérations internes qui peuvent être utilisées au moment de la compilation pour être plus rapides que les opérations utilisateur utilisées au moment de l'exécution.

String() est une fonction interne, donc elle est très rapide, tandis que .toString() interroge la fonction dans le prototype, donc elle n'est pas aussi rapide que new String() est utilisée pour renvoyer une copie exacte.

2. La conversion de nombres à virgule flottante en nombres entiers est plus sujette aux erreurs. Beaucoup de gens aiment utiliser parseInt(). En fait, parseInt() est utilisé pour convertir des chaînes en nombres, pas entre des nombres à virgule flottante et des nombres entiers. devrait utiliser Math.floor() ou Math.round().

De plus, contrairement au problème de recherche d'objet de la section 2, Math est un objet interne, donc Math.floor() n'a en fait pas beaucoup de méthodes de requête et de temps d'appel, et est le plus rapide.

3. Pour les objets personnalisés, si la méthode toString() est définie pour la conversion de type, il est recommandé d'appeler explicitement toString(), car l'opération interne essaiera la méthode toString() de l'objet après avoir essayé toutes les possibilités. si elle peut être convertie en String, donc appeler cette méthode directement sera plus efficace

Utiliser des quantités directes

En fait, cet impact est relativement faible et peut être ignoré. Que signifie utiliser des quantités directes ? Par exemple, JavaScript prend en charge l'utilisation de [param, param, param,...] pour exprimer directement un tableau. Dans le passé, nous utilisions tous new Array(param, param,...) L'utilisation du premier est directement interprétée par le moteur, le second appelle un constructeur interne de Array, il est donc légèrement plus rapide.


De même, var foo = {} est plus rapide que var foo = new Object();, et var reg = /../; est plus rapide que var reg=new RegExp().

Opération de traversée de chaîne

Pour effectuer des opérations de boucle sur des chaînes, telles que le remplacement et la recherche, des expressions régulières doivent être utilisées, car la vitesse de boucle de JavaScript lui-même est relativement lente et le fonctionnement des expressions régulières est une API écrite en C, et les performances sont très bien.

Objets avancés

Les objets avancés personnalisés et les objets Date et RegExp prendront beaucoup de temps pendant la construction. S'il peut être réutilisé, la mise en cache doit être utilisée.

Lié au DOM

Insérer du HTML

De nombreuses personnes aiment utiliser document.write en JavaScript pour générer du contenu pour la page. En fait, c'est moins efficace si vous devez insérer du HTML directement, vous pouvez rechercher un élément conteneur, tel que la spécification d'un div ou d'un span, et définir son innerHTML pour insérer votre propre code HTML dans la page.

Requête d'objet

Utiliser [""] pour interroger est plus rapide que .items() C'est la même chose que l'idée précédente de réduire la recherche d'objets. L'appel de .items() ajoute une requête et un appel de fonction.

Créer un nœud DOM

Habituellement, nous pouvons utiliser des chaînes pour écrire du HTML directement afin de créer des nœuds, mais en réalité, faites-le

La validité du code ne peut être garantie

L'efficacité du fonctionnement des chaînes est faible

Vous devez donc utiliser la méthode document.createElement(), et s'il y a un nœud de modèle prêt à l'emploi dans le document, vous devez utiliser la méthode cloneNode(), car après avoir utilisé la méthode createElement(), vous devez définissez les attributs de l'élément plusieurs fois, utilisez cloneNode() pour réduire le nombre de paramètres d'attribut - de même, si vous devez créer de nombreux éléments, vous devez d'abord préparer un nœud de modèle.


Minuterie

Si vous ciblez du code qui s'exécute en permanence, vous ne devez pas utiliser setTimeout, mais setInterval. setTimeout réinitialise une minuterie à chaque fois.


Autres

Moteur de script

D'après mon test, l'efficacité du JScript de Microsoft est bien pire que celle du Spidermonkey de Mozilla, à la fois en termes de vitesse d'exécution et de gestion de la mémoire, car JScript n'est fondamentalement pas mis à jour actuellement. Mais SpiderMonkey ne peut pas utiliser ActiveXObject


Optimisation des fichiers

L'optimisation des fichiers est également une méthode très efficace. Supprimez tous les espaces et commentaires et mettez le code sur une seule ligne pour accélérer le téléchargement plutôt que la vitesse d'analyse. S'il est local, les commentaires et. Les espaces n'affectent pas l'interprétation et la vitesse d'exécution.

Résumé

Cet article résume certaines des méthodes que j'ai trouvées dans la programmation JavaScript pour améliorer les performances d'exécution de JavaScript. En fait, ces expériences sont basées sur plusieurs principes :


Il est plus rapide d'utiliser simplement ce qui est facilement disponible. Par exemple, les variables locales sont plus rapides que les variables globales, les variables directes sont plus rapides que la construction d'objets au moment de l'exécution, etc.


Réduisez autant que possible le nombre d'exécutions, par exemple en mettant en cache celles qui nécessitent d'abord plusieurs requêtes.


Utilisez autant que possible les fonctionnalités de langage intégrées, telles que les liens de chaîne.


Utilisez autant que possible les API fournies par le système, car ces API sont des codes binaires compilés et ont une efficacité d'exécution élevée


同时,一些基本的算法上的优化,同样可以用在JavaScript中,比如运算结构的调整,这里就不再赘述了。但是由于JavaScript是解释型的,一般不会在运行时对字节码进行优化,所以这些优化仍然是很重要的。

当然,其实这里的一些技巧同样使用在其他的一些解释型语言中,大家也可以进行参考。

由于是以前做过的测试,测试代码已经不全,我补充了一部分如下:

var print; 
if(typeof document != "undefined" ){ 
  print = function(){ 
document.write(arguments[0]); 
} 
}else if(typeof WScript != "undefined" ){ 
  print = function(){ 
    WScript.Echo(arguments[0],arguments[1],arguments[2]); 
  } 
} 
function empty(){ 
} 
function benchmark(f){ 
  var i = 0; 
  var start = (new Date()).getTime(); 
  while(i < pressure){ 
    f(i++); 
  } 
  var end = (new Date()).getTime(); 
  WScript.Echo(end-start); 
} 
/* 
i=0 
start = (new Date()).getTime(); 
while(i < 60000){ 
  c = [i,i,i,i,i,i,i,i,i,i]; 
  i++; 
} 
end = (new Date()).getTime(); 
WScript.Echo(end-start); 
i=0 
start = (new Date()).getTime(); 
while(i < 60000){ 
  c = new Array(i,i,i,i,i,i,i,i,i,i); 
  i++; 
} 
var end = (new Date()).getTime(); 
WScript.Echo(end-start); 
*/ 
function internCast(i){ 
  return "" + i; 
} 
function StringCast(i){ 
  return String(i) 
} 
function newStringCast(i){ 
  return new String(i) 
} 
function toStringCast(i){ 
  return i.toString(); 
} 
function ParseInt(){ 
  return parseInt(j); 
} 
function MathFloor(){ 
  return Math.floor(j); 
} 
function Floor(){ 
  return floor(j); 
} 
var pressure = 50000; 
var a = ""; 
var floor = Math.floor; 
j = 123.123; 
print("-------------\nString Conversion Test"); 
print("The empty:", benchmark(empty)); 
print("intern:", benchmark(internCast)); 
print("String:"); 
benchmark(StringCast); 
print("new String:"); 
benchmark(newStringCast); 
print("toString:"); 
benchmark(toStringCast); 
print("-------------\nFloat to Int Conversion Test"); 
print("parseInt"); 
benchmark(ParseInt); 
print("Math.floor"); 
benchmark(MathFloor); 
print("floor") 
benchmark(Floor); 
function newObject(){ 
  return new Object(); 
} 
function internObject(){ 
  return {}; 
} 
print("------------\nliteral Test"); 
print("runtime new object", benchmark(newObject)); 
print("literal object", benchmark(internObject));  
Copier après la connexion

附录2

代码1:

for(var i=0;i<100;i++){ 
    arr[i]=0; 
  }
Copier après la connexion

代码2:

 var i = 0; 
  while(i < 100){ 
    arr[i++]=0; 
  } 
Copier après la connexion

代码3:

 var i = 0; 
  while(i < 100){ 
    arr[i]=0; 
    i++; 
  }
Copier après la connexion

在firefox下测试这两段代码,结果是代码2优于代码1和3,而代码1一般优于代码3,有时会被代码3超过;而在IE 6.0下,测试压力较大的时候(如测试10000次以上)代码2和3则有时候优于代码1,有时候就会远远落后代码1,而在测试压力较小(如5000次),则代码2>代码3>代码1。

代码4:

var i = 0; 
  var a; 
  while(i < 100){ 
    a = 0; 
    i++; 
  } 
Copier après la connexion

代码5:

 var a; 
  for(var i=0;i<100;i++){ 
    a = 0; 
  } 
Copier après la connexion

上面两段代码在Firefox和IE下测试结果都是性能接近的。

代码6:

  var a; 
  var i=0; 
  while(i<100){ 
    a=i; 
    i++; 
  } 
Copier après la connexion

代码7:

 var a; 
  var i=0; 
  while(i<100){ 
    a=i++; 
  } 
Copier après la connexion

代码8:

 var a; 
  for(var i=0;i<100;i++){ 
    a = i; 
  } 

Copier après la connexion

代码9:

 var a; 
  for(var i=0;i<100;){ 
    a = i++; 
  } 
Copier après la connexion

这四段代码在Firefox下6和8的性能接近,7和9的性能接近,而6, 8 < 7, 9;

最后我们来看一下空循环

代码10:

for(var i=0;i<100;i++){  } 
Copier après la connexion

代码11:

  var i; 
  while(i<100){    i++;  } 
Copier après la connexion

最后的测试出现了神奇的结果,Firefox下代码10所花的时间与代码11所花的大约是24:1。所以它不具备参考价值,于是我没有放在一开始给大家看。

É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
À propos de nous Clause de non-responsabilité Sitemap
Site Web PHP chinois:Formation PHP en ligne sur le bien-être public,Aidez les apprenants PHP à grandir rapidement!