Quelle est la différence entre «Array ()» et «[]» lors de la déclaration d'un tableau JavaScript?

841

Quelle est la vraie différence entre déclarer un tableau comme celui-ci:

var myArray = new Array();

et

var myArray = [];
Amr Elgarhy
la source
[]jeton: ARRAY_INIT; new Arrayjetons: NEW, IDENTIFIER; new Array()jetons:NEW, IDENTIFIER, CALL
noobninja

Réponses:

952

Il y a une différence, mais il n'y a pas de différence dans cet exemple.

En utilisant la méthode plus verbeuse: new Array()a une option supplémentaire dans les paramètres: si vous passez un nombre au constructeur, vous obtiendrez un tableau de cette longueur:

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

Pour illustrer les différentes façons de créer un tableau:

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

;

Une autre différence est que lorsque new Array()vous utilisez, vous pouvez définir la taille du tableau, ce qui affecte la taille de la pile. Cela peut être utile si vous obtenez des débordements de pile ( Performances d'Array.push vs Array.unshift ), ce qui se produit lorsque la taille du tableau dépasse la taille de la pile, et il doit être recréé. Il peut donc en fait, selon le cas d'utilisation, augmenter les performances lors de l'utilisation new Array()car vous pouvez empêcher le débordement de se produire.

Comme indiqué dans cette réponse , new Array(5)n'ajoutera pas réellement cinq undefinedéléments au tableau. Il ajoute simplement de l'espace pour cinq éléments. Sachez que l'utilisation de Arraycette méthode rend difficile la fiabilité array.lengthdes calculs.

nickf
la source
66
C'est un peu faux. Il y a une différence très importante entre new Array () et [] que je développerai dans ma réponse.
coderjoe
30
Mais comme indiqué dans votre réponse, ce n'est différent que si vous êtes complètement fou et écrasez la fonction Array ..?
nickf
19
Eh bien, l'importance est que l'utilisation du nouvel opérateur oblige l'interpréteur à prendre toutes sortes d'étapes supplémentaires pour accéder à la portée globale, rechercher le constructeur, appeler le constructeur et attribuer le résultat ... qui dans le cas majoritaire va être un tableau d'exécution. Vous pouvez éviter les frais généraux liés à la recherche du constructeur global en utilisant simplement []. Cela peut sembler petit, mais lorsque vous effectuez des prises de vue en temps quasi réel dans votre application, cela peut faire une différence.
coderjoe
5
Il y a une énorme différence de performances: jsperf.com/create-an-array-of-initial-size/2
Marco Luglio
4
Certes, mais vous n'avez pas non plus besoin de points-virgules ou de sauts de ligne dans la plupart des endroits où je les ajoute. Il s'agit de cohérence et de lisibilité. Vous savez, à mon humble avis.
nickf
774

La différence entre la création d'un tableau avec le tableau implicite et le constructeur du tableau est subtile mais importante.

Lorsque vous créez un tableau à l'aide de

var a = [];

Vous dites à l'interpréteur de créer un nouveau tableau d'exécution. Aucun traitement supplémentaire nécessaire. Terminé.

Si tu utilises:

var a = new Array();

Vous dites à l'interprète, je veux appeler le constructeur " Array" et générer un objet. Il recherche ensuite dans votre contexte d'exécution pour trouver le constructeur à appeler et l'appelle, créant votre tableau.

Vous pouvez penser "Eh bien, cela n'a pas d'importance du tout. Ce sont les mêmes!". Malheureusement, vous ne pouvez pas garantir cela.

Prenons l'exemple suivant:

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)

Dans l'exemple ci-dessus, le premier appel alertera «SPARTA» comme prévu. Le second ne le sera pas. Vous finirez par voir indéfini. Vous remarquerez également que b contient toutes les fonctions natives de l'objet Array telles que push, là où l'autre ne le fait pas.

Bien que vous puissiez vous attendre à ce que cela se produise, cela illustre simplement le fait que ce []n'est pas la même chose que new Array().

Il est probablement préférable d'utiliser simplement []si vous savez que vous voulez juste un tableau. Je ne suggère pas non plus de faire le tour et de redéfinir Array ...

coderjoe
la source
157
Eh bien, bon à savoir, je suppose. Quel genre de personne écraserait la classe du tableau, je ne sais pas ...
nickf
160
Vous avez absolument raison. Seul un fou écraserait la classe du tableau. Maintenant, prenez un moment et considérez tout le travail supplémentaire que fait le nouveau Array () pour que l'interprète supporte ces fous. J'évite tout cela avec [].
coderjoe
51
Bon exemple du type de pollution globale possible avec JavaScript.
David Snabel-Caunt
8
Il convient de noter que le nouveau tableau (taille) est plus rapide que les autres méthodes possibles utilisant la notation []. Source: jsperf.com/create-an-array-of-initial-size/2
Marco Luglio
9
Malheureusement, ce test est mal préparé. Il teste l'initialisation d'un tableau avec des initialisations de tableaux suivies d'un accès au tableau. Il n'y a aucun contrôle pour prouver que les navigateurs pré-allouent réellement la mémoire (ce que la spécification ne dit pas qu'ils doivent faire). Si nous pouvons supposer que l'accès aux baies est constant et que la majorité du temps sera consacré à l'allocation de mémoire dans les deux exemples, alors [] pourrait être préférable si vous instanciez des millions de baies. jsperf.com/array-instanciation
coderjoe
95

Il y a une différence importante qu'aucune réponse n'a encore mentionnée.

De ceci:

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

Vous pourriez penser que le new Array(2)est équivalent à [undefined, undefined], mais ce n'est PAS!

Essayons avec map():

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

Voir? La sémantique est totalement différente! Alors pourquoi ça?

Selon la spécification ES6 22.1.1.2, le travail de Array(len)consiste simplement à créer un nouveau tableau dont la propriété lengthest définie sur l'argument lenet c'est tout, ce qui signifie qu'il n'y a aucun élément réel à l' intérieur de ce tableau nouvellement créé.

La fonction map(), selon la spécification 22.1.3.15 vérifierait d'abord HasPropertypuis rappellerait , mais il s'avère que:

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

Et c'est pourquoi vous ne pouvez pas vous attendre à ce que les fonctions d'itération fonctionnent comme d'habitude sur les tableaux créés à partir denew Array(len) .

BTW, Safari et Firefox ont une bien meilleure "impression" dans cette situation:

// 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 ]

J'ai déjà soumis un problème à Chromium et je leur demande de corriger cette impression déroutante: https://bugs.chromium.org/p/chromium/issues/detail?id=732021

MISE À JOUR: C'est déjà corrigé. Chrome désormais imprimé comme:

new Array(2)             // (2) [empty × 2]
Hux
la source
22
La vôtre est la seule réponse réelle
Victor
Cela a du sens, je viens de tomber sur une construction différente pour laquelle je ne trouve pas de références documentées: [...Array(2)]ce qui est équivalent [undefined, undefined]du point de vue des résultats.
Roberto Andrade
On dirait que la réponse à mes commentaires précédents est "Opérateur de diffusion": javascript.info/rest-parameters-spread-operator
Roberto Andrade
@RobertoAndrade qui a du sens car l'opérateur de propagation devra lire les entrées pour pouvoir appliquer une telle copie ... et lire un tel retour de slot vide undefinedcomme d'habitude.
Hux
51

Curieusement, il new Array(size)est presque 2x plus rapide que []dans Chrome, et à peu près le même dans FF et IE (mesuré en créant et en remplissant un tableau). Cela n'a d'importance que si vous connaissez la taille approximative du tableau. Si vous ajoutez plus d'éléments que la longueur que vous avez indiquée, l'augmentation des performances est perdue.

Plus précisément: il Array(s'agit d'une opération à temps constant rapide qui n'alloue aucune mémoire, tandis qu'il []s'agit d'une opération à temps linéaire qui définit le type et la valeur.

gblazex
la source
3
Je l'ai beaucoup testé dans Node.js: lorsque vous devez mettre une certaine quantité d'articles dans un tableau, new Array(length)sur 0 <= taille <= ~ 1000, sur la taille> ~ 1000 victoires[]
glukki
40

Pour plus d'informations, la page suivante explique pourquoi vous n'avez jamais besoin d'utilisernew Array()

Vous n'avez jamais besoin d'utiliser new Object()en JavaScript. Utilisez {} plutôt le littéral objet . De même, n'utilisez pas new Array(), utilisez [] plutôt le littéral du tableau . Les tableaux en JavaScript ne fonctionnent en rien comme les tableaux en Java, et l'utilisation de la syntaxe de type Java vous confondra.

Ne pas utiliser new Number, new Stringou new Boolean. Ces formulaires produisent des wrappers d'objets inutiles. Utilisez simplement des littéraux simples à la place.

Consultez également les commentaires - le new Array(length)formulaire ne sert à rien (au moins dans les implémentations actuelles de JavaScript).

BarelyFitz
la source
3
Crockford, aussi, dit d'utiliser [] plutôt que new Array (). Malheureusement, il ne dit pas pourquoi dans l'article lié. Je suppose que c'est juste une question d'espace et de vitesse. javascript.crockford.com/code.html
Nosredna
4
Crockford n'est pas fan de l'utilisation du mot-clé "new" pour créer une nouvelle instance d'un objet en Javascript. Dans les conférences, il a déclaré qu'il croyait que cela crée une ambiguïté et ne correspond pas bien à l'héritage de style prototype de Javascript. Il fait spécifiquement référence aux constructeurs d'objets créés par l'utilisateur, mais étant donné cette croyance, il est facile de comprendre pourquoi il vous recommande de ne pas l'utiliser également avec les fonctionnalités intégrées lorsqu'il existe une syntaxe alternative.
Alan Storm
@Alan Storm: au moins pour Number, String et Boolean, il dit que "ces formulaires produisent des wrappers d'objets inutiles", mais je suppose que cela ne s'appliquerait pas à Array.
BarelyFitz
10

Afin de mieux comprendre []et 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

Le résultat ci-dessus provient de la console Google Chrome sur Windows 7.

Peter Lee
la source
4
mais pourquoi [] == [] ou [] === [] est-il faux?
Anu
5
"Une expression comparant des objets n'est vraie que si les opérandes font référence au même objet." (source: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… )
srph
Cette réponse cherry picks exemples pour impliquer que les deux constructions sont identiques. D'autres publications sur cette page soulignent les différences, telles que Array(3)ou différentes new Array(3)de [3].
ggorlen
8

Le premier est l'appel par défaut du constructeur d'objet. Vous pouvez utiliser ses paramètres si vous le souhaitez.

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

Le second vous donne la possibilité de créer un tableau non vide:

var array = [1, 2, 3]; // this array will contain numbers 1, 2, 3.
Bogdan Gusiev
la source
1
Vous pouvez faire la même chose avec le constructeur verbeux: var array = new Array (1, 2, 3);
nickf
Donc je suppose que vous pouvez le faire en var array = [5]utilisant les crochets mais pas en utilisant le constructeur car cela var array = Array(5)fait un tableau vide de 5 éléments.
cdmckay
cdmckay - c'est incorrect. var a = [5] serait un tableau avec un seul élément - le numéro cinq.
BarelyFitz
2
@BarelyFitz: C'est ce que j'ai dit. Dans la réponse de Bogdans, il dit que l'appel du constructeur ne peut pas être utilisé pour initialiser un tableau, mais il avait tort. Mon commentaire était simplement de préciser que vous ne pouvez pas utiliser l'appel constructeur pour initialiser un tableau d'un seul élément.
cdmckay
1
@cdmckay: désolé, j'ai mal compris votre commentaire. Pour clarifier: nouveau tableau (arg) - si arg est numérique, cela crée un tableau vide avec length = arg; new Array (arg1, arg2) - crée un nouveau tableau et initialise les éléments du tableau. Donc, si vous voulez créer un tableau avec un élément numérique comme [5], vous ne pouvez pas le faire en utilisant new Array (5). Mais vraiment vous ne devriez jamais utiliser new Array () donc c'est un point discutable.
BarelyFitz
5

Je peux expliquer d'une manière plus spécifique en commençant par cet exemple qui est basé sur le bon de 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);

Je viens d'ajouter une autre valeur aux tableaux, et j'ai fait quatre alertes: La première et la seconde doivent nous donner la valeur stockée dans chaque tableau, pour être sûr des valeurs. Ils reviendront les mêmes! Maintenant, essayez le troisième, il renvoie faux, c'est parce que

JS traite test1 comme une VARIABLE avec un type de données de tableau , et il traite test2 comme un OBJET avec la fonctionnalité d'un tableau , et il y a peu de légères différences ici.

La première différence est que lorsque nous appelons test1, il appelle une variable sans réfléchir, il renvoie simplement les valeurs qui sont stockées dans cette variable sans tenir compte de son type de données! Mais, lorsque nous appelons test2, il appelle la fonction Array () , puis il stocke nos valeurs "Pushed" dans sa propriété "Value" , et il en va de même lorsque nous alertons test2, il renvoie la propriété "Value" de l'objet tableau.

Ainsi, lorsque nous vérifions si test1 est égal à test2, bien sûr, ils ne retourneront jamais vrai, l'un est une fonction et l'autre est une variable (avec un type de tableau), même s'ils ont la même valeur!

Pour en être sûr, essayez la 4ème alerte, avec la valeur ajoutée. cela reviendra vrai. Dans ce cas, nous disons à JS "Sans tenir compte du type de conteneur, que ce soit une fonction ou une variable, veuillez comparer les valeurs stockées dans chaque conteneur et dites-nous ce que vous avez vu!" c'est exactement ce qui se passe.

J'espère que j'ai clairement dit l'idée derrière cela, et désolé pour mon mauvais anglais.

Kholio
la source
19
Il est étonnant qu'un tel non-sens complet et absolu ait été voté. La comparaison entre les tableaux sera fausse, peu importe la façon dont vous les créez, car elle compare l'identité de l'objet et ce sont des objets différents. Les tableaux n'ont aucune propriété value. []et new Array()est identique; .valuesera undefineddans les deux cas, et les comparer sera toujours faux.
slikts
D'accord, cette réponse n'a aucun sens et ne montre rien. Il n'y a rien de tel que array.value. et les deux typeof []et typeof new Array()revenir object. C'est l'une des raisons pour lesquelles il existe une fonction appeléeArray.isArray
gman
4

Il n'y a aucune différence lorsque vous initialisez un tableau sans aucune longueur. Donc var a = []& var b = new Array()c'est pareil.

Mais si vous initialisez un tableau avec une longueur comme var b = new Array(1);, il fixera la longueur de l'objet tableau à 1. Donc son équivalent à var b = []; b.length=1;.

Ce sera problématique chaque fois que vous faites array_object.push, il ajoute un élément après le dernier élément et augmente la longueur.

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

contre

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

Le premier est le constructeur d'objet par défaut call.mostly utilisé pour les valeurs dynamiques.

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

le deuxième tableau est utilisé lors de la création de valeurs statiques

var array = [red, green, blue, yellow, white]; // this array will contain values.
Parth Raval
la source
3

Il n'y a pas de grande différence, ils font essentiellement la même chose mais les font de différentes manières, mais lisez la suite, regardez cette déclaration au W3C:

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

et

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

Les deux exemples ci-dessus font exactement la même chose. Il n'est pas nécessaire d'utiliser new Array ().
Pour la simplicité, la lisibilité et la vitesse d'exécution, utilisez la première (la méthode littérale du tableau).

Mais en même temps, créer un nouveau tableau en utilisant une new Arraysyntaxe considérée comme une mauvaise pratique:

Évitez les nouveaux tableaux ()

Il n'est pas nécessaire d'utiliser le nouveau constructeur de tableaux intégré de JavaScript, Array ().
Utilisez [] à la place.
Ces deux instructions différentes créent toutes deux un nouveau tableau vide nommé points:

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

Ces deux instructions différentes créent toutes les deux un nouveau tableau contenant 6 nombres:

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

Le nouveau mot-clé ne fait que compliquer le code. Cela peut également produire des résultats inattendus:

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

Et si je supprime l'un des éléments?

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

Donc, fondamentalement, ce n'est pas considéré comme la meilleure pratique, il y a aussi une différence mineure, vous pouvez passer la longueur à new Array(length)aimer cela, ce qui n'est pas non plus recommandé.

Alireza
la source
Salut Alireza, sont-ils copiés et collés de quelque part? Veuillez ajouter un lien vers la page à partir de laquelle le texte est copié. Consultez cette page du centre d'aide pour plus de détails. Je vous remercie.
Pang
Utile pournew Array(40).fill(123)
gman
2

La différence d'utilisation

var arr = new Array(size);

Ou

arr = [];
arr.length = size;

Comme cela a été suffisamment discuté dans cette question.

Je voudrais ajouter le problème de vitesse - le moyen le plus rapide actuellement , google chromec'est le deuxième.

Mais faites attention, ces choses ont tendance à changer beaucoup avec les mises à jour. De plus, le temps d'exécution variera entre les différents navigateurs.

Par exemple - la 2ème option que j'ai mentionnée, fonctionne à 2 millions [ops / seconde] chrome, mais si vous l'essayez, mozilla dev.vous obtiendrez un taux étonnamment plus élevé de 23 millions.

Quoi qu'il en soit, je vous suggère de le vérifier, de temps en temps, sur différents navigateurs (et machines), en utilisant le site en tant que tel

Meir Elad
la source
2

Comme je sais que la diference u peut trouver la tranche (ou les autres funcitons de Array) comme code1 .and code2 afficher u tableau et ses instances :

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

conclusion:

comme vous pouvez voir []et new Array()créer une nouvelle instance de Array. Et ils obtiennent tous les fonctions prototypes deArray.prototype

Ce ne sont que des instances différentes de Array, ce qui explique pourquoi [] != []

:)

sammy
la source
2

J'ai eu un comportement étrange en utilisant [].

Nous avons des «classes» de modèle avec des champs initialisés à une certaine valeur. Par exemple:

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

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

J'ai trouvé que lorsque les champs sont initialisés avec, []ils seraient partagés par tous les objets Model. Apporter des modifications à l'un affecte tous les autres.

Cela ne se produit pas en les initialisant avec new Array(). Idem pour l'initialisation des objets ( {}vs new Object())

TBH Je ne sais pas si c'est un problème avec le framework que nous utilisions ( Dojo )

algiogia
la source
2

Il y a plus que cela à l'œil nu. La plupart des autres réponses sont correctes MAIS AUSSI ..

new Array(n)

  • Permet au moteur de réallouer de l'espace pour les néléments
  • Optimisé pour la création de baies
  • Le tableau créé est marqué clairsemé qui a les opérations de tableau les moins performantes, c'est parce que chaque accès d'index doit vérifier les limites, voir si la valeur existe et parcourir la chaîne de prototype
  • Si le tableau est marqué comme clairsemé, il n'y a aucun moyen de revenir en arrière (au moins dans V8), il sera toujours plus lent pendant sa durée de vie, même si vous le remplissez avec du contenu (tableau compressé) 1 ms ou 2 heures plus tard, peu importe

[1, 2, 3] || []

  • Le tableau créé est marqué comme emballé (sauf si vous utilisez deleteou la [1,,3]syntaxe)
  • Optimisé pour une matrice des opérations ( for .., forEach, map, etc.)
  • Le moteur doit réallouer de l'espace à mesure que la baie grandit

Ce n'est probablement pas le cas pour les anciennes versions de navigateur / navigateurs.

Solo
la source
-2

J'ai trouvé une différence entre les deux constructions qui me mordait assez fort.

Disons que j'ai:

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

Dans la vraie vie, si je fais ça:

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

Je me retrouve avec ceci:

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

Je ne sais pas ce que la spécification de langage dit censé se produire, mais si je veux que mes deux objets aient des tableaux de propriétés uniques dans mes objets, je dois utiliser new Array().

Bucky
la source
Ce JSFiddle montre que la sortie correspond à ce que vous attendez du littéral de tableau []et du new Array()constructeur, ce qui donne un élément par tableau par propriété. Vous devez avoir quelque chose d'autre en cours dans votre code pour vous retrouver avec le résultat que vous montrez ci-dessus.
gfullam
Bucky, cela ne m'arrive pas, dans aucun navigateur. Pour obtenir ce comportement, vous devez faire quelque chose comme ceci: var property1static=[]; function MyClass(){ this.property1=property1static; this.property2=new Array(); };
Dave Burton
-3

L'utilisation du constructeur Array crée un nouveau tableau de la longueur souhaitée et remplit chacun des indices avec undefined, le tableau affecté à une variable crée les indices pour lesquels vous lui donnez des informations.

Timothy Trousdale
la source
1
Non, le tableau n'est PAS rempli, il n'y a pas d'index / clés à l'intérieur. Par exemple .forEach ne fonctionnerait pas.
CFrei