Perché arr = più veloce di arr = new Array?

Ho eseguito questo codice e ottenuto il risultato sotto. Sono curioso di sapere perché [] è più veloce?

 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') 
  • utilizzando [] : 299 ms
  • usando new : 363ms

Grazie a Raynos ecco un punto di riferimento di questo codice e un modo più ansible per definire una variabile.

inserisci la descrizione dell'immagine qui

Ulteriore espansione delle risposte precedenti …

Da una prospettiva generale dei compilatori e ignorando le ottimizzazioni specifiche della macchina virtuale:

Per prima cosa, passiamo attraverso la fase di analisi lessicale in cui abbiamo tokenize il codice.

A titolo di esempio, possono essere prodotti i seguenti token:

 []: ARRAY_INIT [1]: ARRAY_INIT (NUMBER) [1, foo]: ARRAY_INIT (NUMBER, IDENTIFIER) new Array: NEW, IDENTIFIER new Array(): NEW, IDENTIFIER, CALL new Array(5): NEW, IDENTIFIER, CALL (NUMBER) new Array(5,4): NEW, IDENTIFIER, CALL (NUMBER, NUMBER) new Array(5, foo): NEW, IDENTIFIER, CALL (NUMBER, IDENTIFIER) 

Si spera che questo dovrebbe fornire una visualizzazione sufficiente in modo da poter capire quanto più (o meno) è l’elaborazione richiesta.

  1. Sulla base dei token di cui sopra, sappiamo come un fatto che ARRAY_INIT produrrà sempre un array. Pertanto creiamo semplicemente un array e lo popoliamo. Per quanto riguarda l’ambiguità, la fase di analisi lessicale ha già distinto ARRAY_INIT da una proprietà accessor dell’object (ad esempio obj[foo] ) o parentesi all’interno di stringhe / espressioni regex letterali (ad esempio “foo [] bar” o / [] /)

  2. Questo è minuscolo, ma abbiamo anche più token con la new Array . Inoltre, non è ancora del tutto chiaro che vogliamo semplicemente creare un array. Vediamo il “nuovo” token, ma “nuovo” cosa? Vediamo quindi il token IDENTIFIER che significa che vogliamo una nuova “Array”, ma le VM JavaScript non distinguono generalmente un token IDENTIFIER e token per “oggetti globali nativi”. Perciò…

  3. Dobbiamo cercare la catena di visibilità ogni volta che incontriamo un token IDENTIFIER. Le VM Javascript contengono un “object di triggerszione” per ogni contesto di esecuzione che può contenere l’object “arguments”, le variabili definite localmente, ecc. Se non riusciamo a trovarlo nell’object Activation, iniziamo a cercare la catena dell’ambito fino a raggiungere l’ambito globale . Se non viene trovato nulla, lanciamo un ReferenceError .

  4. Una volta individuata la dichiarazione della variabile, invochiamo il costruttore. new Array è una chiamata di funzione implicita e la regola generale è che le chiamate di funzione sono più lente durante l’esecuzione (ecco perché i compilatori C / C ++ statici consentono la “funzione di inlining” – quali motori JS JIT come SpiderMonkey devono fare al volo )

  5. Il costruttore di Array è sovraccarico. Il costruttore di array viene implementato come codice nativo in modo da fornire alcuni miglioramenti delle prestazioni, ma deve comunque verificare la lunghezza degli argomenti e agire di conseguenza. Inoltre, nel caso in cui venga fornito un solo argomento, è necessario verificare ulteriormente il tipo di argomento. new Array (“foo”) produce [“foo”] dove come nuovo Array (1) produce [indefinito]

Quindi per semplificare tutto: con letterali di array, la VM sa che vogliamo un array; con il new Array , la VM ha bisogno di utilizzare cicli di CPU aggiuntivi per capire cosa fa effettivamente il new Array .

Una ansible ragione è che il new Array richiede una ricerca del nome su Array (si può avere una variabile con quel nome in ambito), mentre [] no.

Buona domanda. Il primo esempio è chiamato un array letterale. È il modo preferito per creare array tra molti sviluppatori. Potrebbe essere che la differenza di prestazioni sia causata controllando gli argomenti della nuova chiamata Array () e quindi creando l’object, mentre il letterale crea direttamente una matrice.

La differenza relativamente piccola nelle prestazioni supporta questo punto, penso. A proposito, si potrebbe fare lo stesso test con l’object e l’object letterale {}.

Questo avrebbe un senso

Gli oggetti letterali ci consentono di scrivere codice che supporta molte funzionalità, ma che rendono ancora relativamente semplice per gli implementatori del nostro codice. Non è necessario richiamare direttamente i costruttori o mantenere l’ordine corretto degli argomenti passati alle funzioni, ecc.

http://www.dyn-web.com/tutorials/obj_lit.php