Qual è la differenza tra "Array ()" e "[]" durante la dichiarazione di un array JavaScript?


841

Qual è la vera differenza tra dichiarare un array come questo:

var myArray = new Array();

e

var myArray = [];

[]token: ARRAY_INIT; new Arraygettoni: NEW, IDENTIFIER; new Array()gettoni:NEW, IDENTIFIER, CALL
noobninja,

Risposte:


952

C'è una differenza, ma non c'è differenza in questo esempio.

Usando il metodo più dettagliato: new Array()ha un'opzione extra nei parametri: se passi un numero al costruttore, otterrai una matrice di quella lunghezza:

x = new Array(5);
alert(x.length); // 5

Per illustrare i diversi modi per creare un array:

var a = [],            // these are the same
    b = new Array(),   // a and b are arrays with length 0

    c = ['foo', 'bar'],           // these are the same
    d = new Array('foo', 'bar'),  // c and d are arrays with 2 strings

    // these are different:
    e = [3]             // e.length == 1, e[0] == 3
    f = new Array(3),   // f.length == 3, f[0] == undefined

;

Un'altra differenza è che quando si utilizza new Array()è possibile impostare la dimensione dell'array, che influisce sulla dimensione dello stack. Ciò può essere utile se si ottengono overflow dello stack ( prestazioni di Array.push vs Array.unshift ) che è ciò che accade quando la dimensione dell'array supera la dimensione dello stack e deve essere ricreata. Quindi, in realtà, a seconda del caso d'uso, si può verificare un aumento delle prestazioni durante l'utilizzo new Array()perché è possibile evitare l'overflow.

Come indicato in questa risposta , new Array(5)non verranno effettivamente aggiunti cinque undefinedelementi all'array. Aggiunge semplicemente spazio per cinque elementi. Essere consapevoli del fatto che l'utilizzo in Arrayquesto modo rende difficile fare affidamento array.lengthper i calcoli.


66
Questo è leggermente sbagliato. C'è una differenza molto importante tra i nuovi array () e [] che elaborerò nella mia risposta.
coderjoe,

30
Ma come notato nella tua risposta, è diverso solo se sei completamente pazzo e sovrascrivi la funzione Array ..?
nickf,

19
Bene, l'importanza è che l'uso del nuovo operatore fa sì che l'interprete compia ogni sorta di passaggi extra per passare all'ambito globale, cercare il costruttore, chiamare il costruttore e assegnare il risultato ... che nella maggior parte dei casi sarà un array di runtime. Puoi evitare il sovraccarico di cercare il costruttore globale semplicemente usando []. Può sembrare piccolo, ma quando scatti per prestazioni quasi in tempo reale nella tua app, può fare la differenza.
coderjoe,

5
C'è un'enorme differenza di prestazioni: jsperf.com/create-an-array-of-initial-size/2
Marco Luglio

4
È vero, ma non hai nemmeno bisogno di punti e virgola o interruzioni di riga nella maggior parte dei luoghi in cui li aggiungo. Si tratta di coerenza e leggibilità. Sai, IMHO.
Nickf

774

La differenza tra la creazione di un array con l'array implicito e il costruttore dell'array è sottile ma importante.

Quando si crea un array usando

var a = [];

Stai dicendo all'interprete di creare un nuovo array di runtime. Nessuna elaborazione extra necessaria affatto. Fatto.

Se usi:

var a = new Array();

Stai dicendo all'interprete, voglio chiamare il costruttore " Array" e generare un oggetto. Quindi cerca nel contesto di esecuzione per trovare il costruttore da chiamare e lo chiama, creando l'array.

Potresti pensare "Beh, questo non ha alcuna importanza. Sono uguali!". Sfortunatamente non puoi garantirlo.

Prendi il seguente esempio:

function Array() {
    this.is = 'SPARTA';
}

var a = new Array();
var b = [];

alert(a.is);  // => 'SPARTA'
alert(b.is);  // => undefined
a.push('Woa'); // => TypeError: a.push is not a function
b.push('Woa'); // => 1 (OK)

Nell'esempio sopra, la prima chiamata avviserà "SPARTA" come ti aspetteresti. Il secondo no. Alla fine vedrai indefinito. Noterai anche che b contiene tutte le funzioni dell'oggetto array nativo come push, dove l'altro no.

Mentre ci si può aspettare che ciò accada, ciò dimostra semplicemente che []non è lo stesso new Array().

Probabilmente è meglio usare solo []se sai che vuoi solo un array. Inoltre, non suggerisco di andare in giro e ridefinire l'array ...


157
Bene, buono a sapersi, suppongo. Che tipo di persona sovrascriverebbe la classe array, non lo so ...
nickf

160
Hai assolutamente ragione. Solo un pazzo avrebbe sovrascritto la classe dell'array. Ora prenditi un momento e considera tutto il lavoro extra che usa il nuovo Array () che fa l'interprete per supportare questi pazzi. Lo evito solo insieme a [].
coderjoe,

51
Un buon esempio del tipo di inquinamento globale che è possibile con JavaScript.
David Snabel-Caunt,

8
Vale la pena notare che il nuovo array (dimensione) è più veloce di altri metodi possibili usando la notazione []. Fonte: jsperf.com/create-an-array-of-initial-size/2
Marco Luglio,

9
Sfortunatamente quel test è preparato in modo improprio. Sta testando un'inizializzazione di un array con inizializzazioni di array seguite dall'accesso all'array. Non c'è controllo per dimostrare che i browser stiano effettivamente pre-allocando la memoria (cosa che la specifica non dice che devono fare). Se possiamo supporre che l'accesso all'array sia costante e che la maggior parte del tempo sarà impiegato per allocare memoria in entrambi gli esempi, allora [] potrebbe essere preferibile se stai istanziando milioni di array. jsperf.com/array-instanciation
coderjoe

95

C'è una differenza importante che nessuna risposta ha ancora menzionato.

Da questa:

new Array(2).length           // 2
new Array(2)[0] === undefined // true
new Array(2)[1] === undefined // true

Potresti pensare che new Array(2)sia equivalente a [undefined, undefined], ma NON lo è!

Proviamo con map():

[undefined, undefined].map(e => 1)  // [1, 1]
new Array(2).map(e => 1)            // "(2) [undefined × 2]" in Chrome

Vedere? La semantica è totalmente diversa! Allora perché?

Secondo ES6 Spec 22.1.1.2, il lavoro di Array(len)è solo la creazione di un nuovo array la cui proprietà lengthè impostata sull'argomento lene il gioco è fatto, il che significa che non c'è alcun elemento reale all'interno di questo array appena creato.

La funzione map(), secondo la specifica 22.1.3.15, verificherebbe innanzitutto HasPropertyla richiamata, ma si scopre che:

new Array(2).hasOwnProperty(0) // false
[undefined, undefined].hasOwnProperty(0) // true

Ed è per questo che non puoi aspettarti che nessuna funzione iterante funzioni come al solito su array creati danew Array(len) .

A proposito, Safari e Firefox hanno una "stampa" molto migliore per questa situazione:

// Safari
new Array(2)             // [](2)
new Array(2).map(e => 1) // [](2) 
[undefined, undefined]   // [undefined, undefined] (2) 

// Firefox
new Array(2)             // Array [ <2 empty slots> ]
new Array(2).map(e => 1) // Array [ <2 empty slots> ]
[undefined, undefined]   // Array [ undefined, undefined ]

Ho già inviato un problema a Chromium e chiedo loro di risolvere questa stampa confusa: https://bugs.chromium.org/p/chromium/issues/detail?id=732021

AGGIORNAMENTO: è già stato corretto. Chrome ora stampato come:

new Array(2)             // (2) [empty × 2]

22
La tua è l'unica vera risposta
Victor,

Questo ha senso, mi sono appena imbattuto in un costrutto diverso per il [...Array(2)]quale non riesco a trovare riferimenti documentati: che è equivalente [undefined, undefined]dal punto di vista dei risultati.
Roberto Andrade,

Sembra che la risposta ai miei precedenti commenti sia "Operatore di diffusione": javascript.info/rest-parameters-spread-operator
Roberto Andrade,

@RobertoAndrade ha senso perché l'operatore di diffusione dovrà leggere le voci in modo da poter applicare tale copia ... e leggere come undefinedal solito un ritorno a slot vuoto .
Hux,

51

Stranamente, new Array(size)è quasi 2 volte più veloce rispetto []a Chrome e circa lo stesso in FF e IE (misurato creando e riempiendo un array). Importa solo se conosci le dimensioni approssimative dell'array. Se aggiungi più elementi della lunghezza che hai indicato, l'incremento delle prestazioni viene perso.

Più precisamente: Array(è un'operazione di tempo costante veloce che non alloca memoria, dov'è []un'operazione di tempo lineare che imposta tipo e valore.


3
L'ho testato molto in Node.js: quando hai bisogno di mettere un certo numero di oggetti in array, new Array(length)su 0 <= size <= ~ 1000, su size> ~ 1000 vittorie[]
glukki


40

Per ulteriori informazioni, la pagina seguente descrive perché non è mai necessario utilizzarlonew Array()

Non hai mai bisogno di usare new Object()in JavaScript. Utilizzare invece l'oggetto letterale {} . Allo stesso modo, non utilizzare new Array(), utilizzare invece l'array letterale [] . Le matrici in JavaScript non funzionano come le matrici in Java e l'uso della sintassi simile a Java ti confonderà.

Non utilizzare new Number, new Stringo new Boolean. Questi moduli producono involucri di oggetti non necessari. Basta usare letterali semplici invece.

Dai un'occhiata anche ai commenti: il new Array(length)modulo non ha alcuno scopo utile (almeno nelle implementazioni odierne di JavaScript).


3
Crockford, inoltre, dice di usare [] piuttosto che il nuovo Array (). Sfortunatamente, non dice perché nell'articolo collegato. Presumo sia solo una questione di spazio e velocità. javascript.crockford.com/code.html
Nosredna,

4
Crockford non è un fan dell'utilizzo della parola chiave "new" per creare una nuova istanza di un oggetto in Javascript. Nelle lezioni ha affermato che crede che crei ambiguità e non si adatti bene all'eredità dello stile prototipo di Javascript. Si riferisce in particolare ai costruttori di oggetti creati dall'utente, ma data questa convinzione, è facile capire perché ti consiglierebbe di non usarlo anche con i built-in quando c'è una sintassi alternativa.
Alan Storm,

@Alan Storm: almeno per Number, String e Boolean afferma che "questi moduli producono involucri di oggetti non necessari", ma immagino che non si applicherebbe all'array.
BarelyFitz,

10

Al fine di comprendere meglio []e new Array():

> []
  []
> new Array()
  []
> [] == []
  false
> [] === []
  false
> new Array() == new Array()
  false
> new Array() === new Array()
  false
> typeof ([])
  "object"
> typeof (new Array())
  "object"
> [] === new Array()
  false
> [] == new Array()
  false

Il risultato sopra è dalla console di Google Chrome su Windows 7.


4
ma perché [] == [] o [] === [] è falso?
anu

5
"Un'espressione che confronta oggetti è vera solo se gli operandi fanno riferimento allo stesso oggetto." (fonte: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… )
srph

Questa risposta mostra esempi per suggerire che i due costrutti sono identici. Altri post in questa pagina sottolineano le differenze, come Array(3)o new Array(3)non è la stessa di [3].
Ggorlen,

8

Il primo è la chiamata del costruttore dell'oggetto predefinita. Puoi usare i suoi parametri se vuoi.

var array = new Array(5); //initialize with default length 5

Il secondo ti dà la possibilità di creare array non vuoti:

var array = [1, 2, 3]; // this array will contain numbers 1, 2, 3.

1
Puoi fare la stessa cosa con il costruttore dettagliato: var array = new Array (1, 2, 3);
nickf

Quindi suppongo che tu possa fare var array = [5]usando le parentesi quadre ma non usando il costruttore come var array = Array(5)fa una matrice vuota di 5 elementi.
cdmckay,

cdmckay - non è corretto. var a = [5] sarebbe un array con un singolo elemento - il numero cinque.
BarelyFitz,

2
@BarelyFitz: è quello che ho detto. Nella risposta di Bogdans, afferma che la chiamata del costruttore non può essere utilizzata per inizializzare un array, ma ha sbagliato. Il mio commento è stato semplicemente per chiarire che non è possibile utilizzare la chiamata del costruttore per inizializzare una matrice di un singolo elemento.
cdmckay,

1
@cdmckay: scusa, ho frainteso il tuo commento. Per chiarire: new Array (arg) - se arg è numerico, questo crea un array vuoto con length = arg; new Array (arg1, arg2): crea un nuovo array e inizializza gli elementi dell'array. Quindi, se si desidera creare un array con un elemento numerico come [5], non è possibile farlo utilizzando il nuovo array (5). Ma davvero non dovresti mai usare il nuovo Array () quindi questo è un punto controverso.
BarelyFitz,

5

Posso spiegare in un modo più specifico a partire da questo esempio basato su quello buono di Fredrik.

var test1 = [];
test1.push("value");
test1.push("value2");

var test2 = new Array();
test2.push("value");
test2.push("value2");

alert(test1);
alert(test2);
alert(test1 == test2);
alert(test1.value == test2.value);

Ho appena aggiunto un altro valore alle matrici e ho emesso quattro avvisi: il primo e il secondo servono a fornirci il valore memorizzato in ciascun array, per essere sicuri dei valori. Restituiranno lo stesso! Ora prova il terzo, restituisce false, questo perché

JS considera test1 come VARIABILE con un tipo di dati di array e tratta test2 come un OGGETTO con la funzionalità di un array , e qui ci sono alcune lievi differenze.

La prima differenza è quando chiamiamo test1 chiama una variabile senza pensare, restituisce semplicemente i valori memorizzati in questa variabile ignorando il suo tipo di dati! Ma quando chiamiamo test2 chiama la funzione Array () e quindi memorizza i nostri valori "Pushed" nella sua proprietà "Value" , e lo stesso accade quando avvisiamo test2, restituisce la proprietà "Value" dell'oggetto array.

Quindi quando controlliamo se test1 è uguale a test2 ovviamente non restituiranno mai true, una è una funzione e l'altra è una variabile (con un tipo di array), anche se hanno lo stesso valore!

Per essere sicuri, prova il 4 ° avviso, con il valore .value aggiunto ad esso; tornerà vero. In questo caso diciamo a JS "Ignorando il tipo di contenitore, che si tratti di funzione o variabile, si prega di confrontare i valori memorizzati in ciascun contenitore e di dirci cosa hai visto!" è esattamente quello che succede.

Spero di aver detto chiaramente l'idea alla base, e mi dispiace per il mio cattivo inglese.


19
È sorprendente che siano state votate tali sciocchezze complete ed assolute. Il confronto tra le matrici sarà falso, non importa come le crei perché confronta l'identità dell'oggetto e sono oggetti diversi. Le matrici non hanno proprietà di valore. []ed new Array()è identico; .valuesarà undefinedin entrambi i casi, e confrontarli sarà sempre falso.
scivola il

D'accordo, questa risposta non ha senso e non mostra nulla. Non esiste array.value. ed entrambi typeof []e typeof new Array()ritorno object. È uno dei motivi per cui esiste una funzione chiamataArray.isArray
gman

4

Non vi è alcuna differenza quando si inizializza l'array senza alcuna lunghezza. Quindi var a = []ed var b = new Array()è lo stesso.

Ma se inizializzi l'array con una lunghezza simile var b = new Array(1);, imposterà la lunghezza dell'oggetto array su 1. Quindi è equivalente a var b = []; b.length=1;.

Ciò sarà problematico ogni volta che esegui array_object.push, aggiungerà l'elemento dopo l'ultimo elemento e aumenterà la lunghezza.

var b = new Array(1);
b.push("hello world");
console.log(b.length); // print 2

vs

var v = [];
a.push("hello world");
console.log(b.length); // print 1

3

Il primo è il costruttore di oggetti predefinito call.mostly utilizzato per valori dinamici.

var array = new Array(length); //initialize with default length

il secondo array viene utilizzato durante la creazione di valori statici

var array = [red, green, blue, yellow, white]; // this array will contain values.

3

Non c'è alcuna grande differenza, sostanzialmente fanno la stessa cosa ma li fanno in modi diversi, ma continuate a leggere, guardate questa affermazione su W3C:

var cars = ["Saab", "Volvo","BMW"];

e

var cars = new Array("Saab", "Volvo", "BMW");

I due esempi sopra fanno esattamente lo stesso. Non è necessario utilizzare il nuovo array ().
Per semplicità, leggibilità e velocità di esecuzione, utilizzare il primo (il metodo letterale array).

Ma allo stesso tempo, creare un nuovo array usando la new Arraysintassi considerata una cattiva pratica:

Evitare nuovi array ()

Non è necessario utilizzare il nuovo costruttore di array incorporato JavaScript (Array).
Utilizzare invece [].
Queste due diverse istruzioni creano entrambe un nuovo array vuoto chiamato punti:

var points = new Array();         // Bad
var points = [];                  // Good 

Queste due diverse istruzioni creano entrambe un nuovo array contenente 6 numeri:

var points = new Array(40, 100, 1, 5, 25, 10); // Bad    
var points = [40, 100, 1, 5, 25, 10];          // Good

La nuova parola chiave complica solo il codice. Può anche produrre alcuni risultati inaspettati:

var points = new Array(40, 100);  // Creates an array with two elements (40 and 100)

Cosa succede se rimuovo uno degli elementi?

var points = new Array(40);       // Creates an array with 40 undefined elements !!!!!

Quindi praticamente non è considerata la migliore pratica, anche lì c'è una differenza minore, puoi passare la lunghezza a new Array(length)questo, che non è un modo raccomandato.


Ciao Alireza, sono copiati e incollati da qualche parte? Aggiungi un link alla pagina da cui viene copiato il testo. Consulta questa pagina del Centro assistenza per i dettagli. Grazie.
Ha suonato

Utile pernew Array(40).fill(123)
gman il

2

La differenza di utilizzo

var arr = new Array(size);

O

arr = [];
arr.length = size;

Come discusso abbastanza in questa domanda.

Vorrei aggiungere il problema della velocità - l' attuale modo più veloce, sugoogle chrome è il secondo.

Ma attenzione, queste cose tendono a cambiare molto con gli aggiornamenti. Anche il tempo di esecuzione differirà tra i diversi browser.

Ad esempio, la seconda opzione che ho menzionato, funziona a 2 milioni [ops / secondo] in poi chrome, ma se lo provassi sumozilla dev. otterresti un tasso sorprendentemente più alto di 23 milioni.

Ad ogni modo, ti suggerisco di provarlo, di tanto in tanto, su diversi browser (e macchine), usando il sito come tale


2

Come so la differenza puoi trovare la sezione (o le altre funzioni di Array) come code1 .e code2 mostrano u Array e le sue istanze :

code1:

[].slice; // find slice here
var arr = new Array();
arr.slice // find slice here
Array.prototype.slice // find slice here

code2:

[].__proto__ == Array.prototype; // true
var arr = new Array();
arr.__proto__ == Array.prototype; // true

conclusione:

come puoi vedere []e new Array()creare una nuova istanza di Array. Tutti ottengono le funzioni del prototipoArray.prototype

Sono solo diversi esempi di Array.Questo spiega perché [] != []

:)


2

Ho avuto un comportamento strano usando [].

Abbiamo "classi" di modello con campi inizializzati su un valore. Per esempio:

require([
  "dojo/_base/declare",
  "dijit/_WidgetBase",
], function(declare, parser, ready, _WidgetBase){

   declare("MyWidget", [_WidgetBase], {
     field1: [],
     field2: "",
     function1: function(),
     function2: function()
   });    
});

Ho scoperto che quando i campi sono inizializzati con []allora sarebbero condivisi da tutti gli oggetti Model. Apportare modifiche a uno influisce su tutti gli altri.

Questo non accade inizializzandoli con new Array(). Lo stesso per l'inizializzazione di oggetti ( {}vs nuovo Object())

TBH Non sono sicuro che si tratti di un problema con il framework che stavamo usando ( Dojo )


2

C'è di più in questo di quanto sembri. La maggior parte delle altre risposte sono corrette, MA ANCHE ..

new Array(n)

  • Consente al motore di riallocare lo spazio per gli nelementi
  • Ottimizzato per array creazione di
  • L'array creato è contrassegnato come sparso che ha le operazioni dell'array meno performanti, perché ogni accesso all'indice deve controllare i limiti, vedere se esiste un valore e percorrere la catena del prototipo
  • Se l'array è contrassegnato come scarso, non c'è modo di tornare indietro (almeno in V8), sarà sempre più lento durante la sua vita, anche se lo riempi di contenuto (array compresso) 1ms o 2 ore dopo, non importa

[1, 2, 3] || []

  • L'array creato è contrassegnato come compresso (a meno che non si utilizzi deleteo [1,,3]sintassi)
  • Ottimizzato per matrice operazioni ( for .., forEach, map, ecc)
  • Il motore deve riallocare lo spazio man mano che l'array cresce

Questo probabilmente non è il caso delle versioni / browser precedenti.


-2

Ho trovato una differenza tra le due costruzioni che mi ha morso piuttosto duramente.

Diciamo che ho:

function MyClass(){
  this.property1=[];
  this.property2=new Array();
};
var MyObject1=new MyClass();
var MyObject2=new MyClass();

Nella vita reale, se lo faccio:

MyObject1.property1.push('a');
MyObject1.property2.push('b');
MyObject2.property1.push('c');
MyObject2.property2.push('d');

Quello che finisco è questo:

MyObject1.property1=['a','c']
MyObject1.property2=['b']
MyObject2.property1=['a','c']
MyObject2.property2=['d']

Non so cosa dovrebbe succedere la specifica del linguaggio, ma se voglio che i miei due oggetti abbiano array di proprietà univoci nei miei oggetti, devo usare new Array().


Questo JSFiddle mostra che l'output è quello che ti aspetteresti dall'array letterale []e dal new Array()costruttore risultante in un elemento per array per proprietà. Devi avere qualcos'altro nel tuo codice per finire con il risultato che mostri sopra.
gfullam,

Bucky, non succede per me, in nessun browser. Per ottenere quel comportamento dovresti fare qualcosa del genere: var property1static=[]; function MyClass(){ this.property1=property1static; this.property2=new Array(); };
Dave Burton

-3

Usando il costruttore Array crea un nuovo array della lunghezza desiderata e popola ciascuno degli indici con indefinito, l'assegnazione di un array a una variabile crea gli indici per i quali fornisci informazioni.


1
No, l'array NON è popolato, non ci sono indici / chiavi all'interno. Ad esempio .forEach non funzionerebbe.
CFrei il
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.