web-dev-qa-db-fra.com

Comment initialiser la longueur d'un tableau en javascript?

La plupart des tutoriels que j'ai lus sur des tableaux en JavaScript (y compris w3schools et devgur ) suggèrent que vous pouvez initialiser un tableau avec une certaine longueur en transmettant un entier à la Constructeur de tableau utilisant la syntaxe var test = new Array(4);.

Après avoir utilisé cette syntaxe de manière généralisée dans mes fichiers js, j'ai exécuté l'un des fichiers via jsLint , et cela a flippé:

Erreur: Problème à la ligne 1, caractère 22: attendu ')' et à la place vu '4'.
var test = new Array (4);
Problème à la ligne 1, caractère 23: attendu ';' et a plutôt vu ')'.
var test = new Array (4);
Problème à la ligne 1, caractère 23: Identifiant attendu et à la place, vu ')'.

Après avoir lu l'explication de jsLint sur son comportement , il semble que jsLint n'aime pas vraiment la syntaxe new Array(), mais préfère plutôt [] lors de la déclaration de tableaux.

J'ai donc quelques questions. D'abord, pourquoi? Est-ce que je prends des risques en utilisant plutôt la syntaxe new Array()? Existe-t-il des incompatibilités de navigateur dont je devrais être au courant? Et deuxièmement, si je passe à la syntaxe des crochets, existe-t-il un moyen de déclarer un tableau et de définir sa longueur sur une seule ligne, ou dois-je faire quelque chose comme ça:

var test = [];
test.length = 4;
447
  1. Pourquoi voulez-vous initialiser la longueur? Théoriquement, cela n'est pas nécessaire. Cela peut même entraîner un comportement déroutant, car tous les tests utilisant la variable length pour savoir si un tableau est vide ou non indiqueront que le tableau n'est pas vide.
    Certainstests montrent que la définition de la longueur initiale de grands tableaux peut être plus efficace si le tableau est remplies par la suite, mais le gain de performance (le cas échéant) semble différer d’un navigateur à l’autre.

  2. jsLint n'aime pas new Array() parce que le constructeur est ambigu.

    new Array(4);
    

    crée un tableau vide de longueur 4. Mais

    new Array('4');
    

    crée un tableau contenant la valeur '4'.

Concernant votre commentaire: Dans JS, vous n'avez pas besoin d'initialiser la longueur du tableau. Ça pousse dynamiquement. Vous pouvez simplement stocker la longueur dans une variable, par exemple.

var data = [];
var length = 5; // user defined length

for(var i = 0; i < length; i++) {
    data.Push(createSomeObject());
}
347
Felix Kling
  • Array(5) vous donne un tableau de longueur 5 mais pas de valeur, vous ne pouvez donc pas le parcourir.

  • Array.apply(null, Array(5)).map(function () {}) vous donne un tableau de longueur 5 et non défini comme valeur, il peut maintenant être itéré.

  • Array.apply(null, Array(5)).map(function (x, i) { return i; }) vous donne un tableau de longueur 5 et de valeurs 0,1,2,3,4.

  • Array(5).forEach(alert) ne fait rien, Array.apply(null, Array(5)).forEach(alert) vous donne 5 alertes

  • ES6 nous donne Array.from pour que vous puissiez maintenant utiliser aussi Array.from(Array(5)).forEach(alert)

  • Si vous voulez initialiser avec une certaine valeur, il est bon de le savoir ...
    Array.from('abcde'), Array.from('x'.repeat(5))
    or Array.from({length: 5}, (v, i) => i) // gives [0, 1, 2, 3, 4]

458
Ruben Stolk

Avec ES2015 .fill() vous pouvez maintenant faire simplement:

// `n` is the size you want to initialize your array
// `0` is what the array will be filled with (can be any other value)
Array(n).fill(0)

Ce qui est beaucoup plus concis que Array.apply(0, new Array(n)).map(i => value)

Il est possible de supprimer le 0 dans .fill() et de l'exécuter sans argument, ce qui remplira le tableau avec undefined. ( Cependant, cela échouera dans TypeScript )

209
AP.

Le plus court:

[...Array(1000)]
61
Michael Mammoliti
[...Array(6)].map(x=>0);

// [0, 0, 0, 0, 0, 0]

OU

Array(6).fill(0);

// [0, 0, 0, 0, 0, 0]

Remarque: vous ne pouvez pas mettre en boucle les logements vides Array(4).forEach( (_,i) => {} )

OU

Array(6).fill(null).map( (x,i) => i );

// [0, 1, 2, 3, 4, 5]

( TypeScript safe )


Création de tableaux imbriqués

Lors de la création d'un tableau 2D avec fill intuitivement, il convient de créer de nouvelles instances. Mais ce qui va réellement se passer, c'est que le même tableau sera stocké en tant que référence.

var a = Array(3).fill([6]); 
// [[6], [6], [6]]

a[ 0 ].Push( 9 );
// [[6,9], [6,9], [6,9]]

Solution

var a = [...Array(3)].map(x=>[]); 

a[ 0 ].Push( 4, 2 );
// [[4,2], [ ], [ ]]

Ainsi, un tableau 3x2 ressemblera à ceci:

[...Array(3)].map(x=>Array(2).fill(0));

// [ [0,0] ,
//   [0,0] ,
//   [0,0] ]

Initialiser un échiquier

var Chessboard = [...Array( 8 )].map( (x,j) =>
    Array( 8 ).fill( null ).map( (y,i) =>
        `${ String.fromCharCode( 65 + i ) }${ 8 - j }`));

// [ [ A8,B8,C8,D8,E8,F8,G8,H8 ],
//   [ A7,B7,C7,D7,E7,F7,G7,H7 ],
//   [ A6,B6,C6,D6,E6,F6,G6,H6 ],
//   [ A5,B5,C5,D5,E5,F5,G5,H5 ],
//   [ A4,B4,C4,D4,E4,F4,G4,H4 ],
//   [ A3,B3,C3,D3,E3,F3,G3,H3 ],
//   [ A2,B2,C2,D2,E2,F2,G2,H2 ],
//   [ A1,B1,C1,D1,E1,F1,G1,H1 ] ]
49
Vlad

ES6 introduit Array.from qui vous permet de créer un Array à partir de n’importe quel "semblable à un tableau" ou iterables objets:

_Array.from({length: 10}, (x, i) => i);
// [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
_

Dans ce cas, _{length: 10}_ représente la définition minimale d'un objet "semblable à un tableau" : un objet vide avec juste un length propriété définie.

Array.from permet à un deuxième argument d'être mappé sur le tableau résultant.

33
Alexander Shutau

Cela initialisera la propriété length à 4:

var x = [,,,,];
25
Šime Vidas

Je suis surpris qu'il n'y ait pas eu de solution fonctionnelle suggérée vous permettant de définir la longueur sur une seule ligne. Ce qui suit est basé sur UnderscoreJS:

var test = _.map(_.range(4), function () { return undefined; });
console.log(test.length);

Pour les raisons mentionnées ci-dessus, je ne le ferais que si je voulais initialiser le tableau avec une valeur spécifique. Il est intéressant de noter que d'autres bibliothèques implémentent la gamme, notamment Lo-dash et Lazy, qui peuvent présenter des caractéristiques de performances différentes.

16
christang

(c'était probablement mieux comme commentaire, mais c'est devenu trop long)

Donc, après avoir lu ceci, j'étais curieux de savoir si la pré-allocation était réellement plus rapide, car en théorie cela devrait être. Cependant, ce blog a donné quelques conseils contre elle http://www.html5rocks.com/en/tutorials/speed/v8/ .

Donc, toujours incertain, je l'ai mis à l'épreuve. Et comme il s'avère que cela semble en fait être plus lent.

var time = Date.now();
var temp = [];
for(var i=0;i<100000;i++){
    temp[i]=i;
}
console.log(Date.now()-time);


var time = Date.now();
var temp2 = new Array(100000);
for(var i=0;i<100000;i++){
    temp2[i] = i;
}
console.log(Date.now()-time); 

Ce code donne les résultats suivants après quelques exécutions occasionnelles:

$ node main.js 
9
16
$ node main.js 
8
14
$ node main.js 
7
20
$ node main.js 
9
14
$ node main.js 
9
19
8
j03m

S'il vous plaît, les gens n'abandonnent pas vos anciennes habitudes pour l'instant. Il y a une grande différence de vitesse entre allouer une fois la mémoire puis utiliser les entrées de ce tableau (comme auparavant) et l'allouer plusieurs fois à mesure que le tableau s'agrandit (ce qui est inévitablement ce que le système fait sous le capot avec d'autres méthodes suggérées) .

Bien sûr, rien de tout cela n’a d’importance à moins de vouloir faire quelque chose de cool avec des baies plus grandes. Alors ça le fait.

Comme il semble toujours n'y avoir aucune option dans JS pour le moment pour définir la capacité initiale d'un tableau, j'utilise ce qui suit ...

var newArrayWithSize = function(size) {
  this.standard = this.standard||[];
  for (var add = size-this.standard.length; add>0; add--) {
   this.standard.Push(undefined);// or whatever
  }
  return this.standard.slice(0,size);
}

Il y a des compromis impliqués:

  • Cette méthode prend autant de temps que les autres pour le premier appel de la fonction, mais très peu de temps pour les appels ultérieurs (à moins de demander un tableau plus grand).
  • Le tableau standard réserve en permanence autant d’espace que le tableau le plus grand que vous avez demandé.

Mais si cela correspond à ce que vous faites, cela peut être rentable. Timing informel met

for (var n=10000;n>0;n--) {var b = newArrayWithSize(10000);b[0]=0;}

assez rapide (environ 50 ms pour le 10000 étant donné qu'avec n = 1000000, il a fallu environ 5 secondes), et

for (var n=10000;n>0;n--) {
  var b = [];for (var add=10000;add>0;add--) {
    b.Push(undefined);
  }
}

bien au-dessus d’une minute (environ 90 secondes pour le 10000 sur la même console chrome, ou environ 2000 fois plus lentement). Ce ne sera pas seulement l'allocation, mais aussi les 10000 push, pour la boucle, etc.

7
wils
var arr=[];
arr[5]=0;
alert("length="+arr.length); // gives 6
7
user1067305

Voici une autre solution

var arr = Array.apply( null, { length: 4 } );
arr;  // [undefined, undefined, undefined, undefined] (in Chrome)
arr.length; // 4

Le premier argument de apply() est une liaison d'objet this, dont nous ne nous soucions pas ici, nous l'avons donc définie sur null.

Array.apply(..) appelle la fonction Array(..) et étale la valeur de l'objet { length: 3 } en tant qu'argument.

6
zangw

Le constructeur de tableau a un syntaxe ambiguë , et JSLint blesse juste vos sentiments après tout.

En outre, votre exemple de code est cassé, la deuxième instruction var lève un SyntaxError. Vous définissez la propriété length du tableau test, vous n'avez donc pas besoin d'un autre var.

En ce qui concerne vos options, array.length est le seul "propre". La question est, pourquoi avez-vous besoin de définir la taille en premier lieu? Essayez de refactoriser votre code pour vous débarrasser de cette dépendance.

3
Ivo Wetzel

Comme expliqué ci-dessus, utiliser new Array(size) est quelque peu dangereux. Au lieu de l'utiliser directement, placez-le dans une "fonction de créateur de tableau". Vous pouvez facilement vous assurer que cette fonction est sans bug et vous évitez le danger d'appeler directement new Array(size). En outre, vous pouvez lui attribuer une valeur initiale par défaut facultative. Cette fonction createArray fait exactement cela:

function createArray(size, defaultVal) {
    var arr = new Array(size);
    if (arguments.length == 2) {
        // optional default value
        for (int i = 0; i < size; ++i) {
            arr[i] = defaultVal;
        }
    }
    return arr;
}
2
Domi

En supposant que la longueur de Array soit constante. En Javascript, voici ce que nous faisons:

const intialArray = new Array(specify the value);

2
mohan babu

La raison pour laquelle vous ne devriez pas utiliser new Array est illustrée par ce code:

var Array = function () {};

var x = new Array(4);

alert(x.length);  // undefined...

Un autre code pourrait foiré avec la variable Array. Je sais que c'est un peu ridicule que quiconque écrit un tel code, mais quand même ...

En outre, comme Felix King l’a dit, l’interface est un peu incohérente et pourrait donner lieu à des bogues très difficiles à détecter.

Si vous voulez un tableau de longueur = x, rempli avec undefined (comme le ferait new Array(x), vous pouvez le faire:

var x = 4;
var myArray = [];
myArray[x - 1] = undefined;

alert(myArray.length); // 4
0
nickf