J'ai exécuté ce code et j'ai obtenu le résultat ci-dessous. Je suis curieux de savoir pourquoi []
est plus rapide?
console.time('using[]')
for(var i=0; i<200000; i++){var arr = []};
console.timeEnd('using[]')
console.time('using new')
for(var i=0; i<200000; i++){var arr = new Array};
console.timeEnd('using new')
- en utilisant
[]
: 299ms - en utilisant
new
: 363ms
Grâce à Raynos, voici un benchmark de ce code et une autre manière possible de définir une variable.
javascript
performance
Mohsen
la source
la source
[]
dire équivaut ànew Array()
en termes de code source, pas d'objets renvoyés sous forme d'expressionsRéponses:
Élargir davantage les réponses précédentes ...
Du point de vue général des compilateurs et sans tenir compte des optimisations spécifiques aux VM:
Tout d'abord, nous passons par la phase d'analyse lexicale où nous tokenisons le code.
A titre d'exemple, les jetons suivants peuvent être produits:
J'espère que cela devrait vous fournir une visualisation suffisante pour que vous puissiez comprendre combien de traitement est nécessaire.
Sur la base des jetons ci-dessus, nous savons que ARRAY_INIT produira toujours un tableau. Nous créons donc simplement un tableau et le peuplons. En ce qui concerne l'ambiguïté, l'étape d'analyse lexicale a déjà distingué ARRAY_INIT d'un accesseur de propriété d'objet (par exemple
obj[foo]
) ou de crochets à l'intérieur de chaînes / littéraux regex (par exemple "foo [] bar" ou / [] /)C'est minuscule, mais nous avons aussi plus de jetons avec
new Array
. De plus, il n'est pas encore tout à fait clair que nous souhaitons simplement créer un tableau. On voit le «nouveau» jeton, mais «nouveau» quoi? Nous voyons alors le jeton IDENTIFIER qui signifie que nous voulons un nouveau «tableau», mais les VM JavaScript ne distinguent généralement pas un jeton IDENTIFIER et des jetons pour les «objets globaux natifs». Par conséquent...Nous devons rechercher la chaîne de portée chaque fois que nous rencontrons un jeton IDENTIFIER. Les VM Javascript contiennent un "objet Activation" pour chaque contexte d'exécution qui peut contenir l'objet "arguments", des variables définies localement, etc. Si nous ne pouvons pas le trouver dans l'objet Activation, nous commençons à rechercher la chaîne de portée jusqu'à ce que nous atteignions la portée globale . Si rien n'est trouvé, nous lançons un fichier
ReferenceError
.Une fois que nous avons localisé la déclaration de variable, nous appelons le constructeur.
new Array
est un appel de fonction implicite, et la règle de base est que les appels de fonction sont plus lents pendant l'exécution (d'où la raison pour laquelle les compilateurs statiques C / C ++ autorisent la "fonction en ligne" - ce que les moteurs JS JIT tels que SpiderMonkey doivent faire à la volée)Le
Array
constructeur est surchargé. Le constructeur Array est implémenté en tant que code natif, il fournit donc des améliorations de performances, mais il doit toujours vérifier la longueur des arguments et agir en conséquence. De plus, dans le cas où un seul argument est fourni, nous devons vérifier davantage le type de l'argument. new Array ("foo") produit ["foo"] où comme new Array (1) produit [undefined]Donc, pour simplifier tout cela: avec les littéraux de tableau, la VM sait que nous voulons un tableau; avec
new Array
, la machine virtuelle doit utiliser des cycles CPU supplémentaires pour déterminer ce quenew Array
fait réellement .la source
Une raison possible est que cela
new Array
nécessite une recherche de nomArray
(vous pouvez avoir une variable avec ce nom dans la portée), alors que ce[]
n'est pas le cas.la source
Array
exclut à la fois un argumentlen
et plusieurs arguments. Où as[]
n'accepte que plusieurs arguments. De plus, les tests de Firefox ne montrent presque aucune différence.var Array = window.Array
améliore les performances dunew Array
test.Bonne question. Le premier exemple est appelé un littéral de tableau. C'est le moyen préféré de créer des tableaux parmi de nombreux développeurs. Il se peut que la différence de performances soit causée par la vérification des arguments du nouvel appel Array () puis la création de l'objet, tandis que le littéral crée directement un tableau.
Je pense que la différence de performances relativement faible confirme ce point. Vous pouvez faire le même test avec le littéral Object et object {} d'ailleurs.
la source
Cela aurait du sens
http://www.dyn-web.com/tutorials/obj_lit.php
la source
Aussi, intéressant, si la longueur du tableau est connue à l'avance (les éléments seront ajoutés juste après la création), l'utilisation d'un constructeur de tableau avec une longueur spécifiée est beaucoup plus rapide sur les récents Google Chrome 70+.
" new Array ( % ARR_LENGTH% ) " - 100% (plus rapide) !
" [] " - 160-170% (plus lent)
Le test peut être trouvé ici - https://jsperf.com/small-arr-init-with-known-length-brackets-vs-new-array/2
Remarque: ce résultat testé sur Google Chrome v.70 + ; dans Firefox v.70 et IE, les deux variantes sont presque égales.
la source