web-dev-qa-db-fra.com

Les tableaux Javascript sont-ils rares?

Autrement dit, si j'utilise l'heure actuelle comme index dans le tableau:

array[Date.getTime()] = value;

l'interpréteur instanciera-t-il tous les éléments de 0 à maintenant? Les différents navigateurs le font-ils différemment?

Je me souviens qu'il y avait un bug dans le noyau AIX , qui créerait des pseudo-ttys sur demande, mais si vous le faisiez, dites "echo>/dev/pty10000000000 "cela créerait/dev/pty0,/dev/pty1, .... et tomberait alors mort. C'était amusant lors de salons, mais je ne veux pas que cela arrive à mes clients.

90
Berry

La manière exacte dont les tableaux JavaScript sont mis en œuvre diffère d'un navigateur à l'autre, mais ils retombent généralement sur une implémentation clairsemée - probablement la même que celle utilisée pour l'accès aux propriétés des objets normaux - si l'utilisation d'un tableau réel serait inefficace.

Vous devrez demander à quelqu'un qui a plus de connaissances sur des implémentations spécifiques de répondre à ce qui déclenche de manière excessive le passage de dense à clairsemé, mais votre exemple devrait être parfaitement sûr. Si vous voulez obtenir un tableau dense, vous devez appeler le constructeur avec un argument de longueur explicite et espérer que vous en obtiendrez un.

Voir cette réponse pour une description plus détaillée par olliej.

36
Christoph

Oui, ils sont. Ce sont en fait des tables de hachage en interne, vous pouvez donc utiliser non seulement de grands nombres entiers mais aussi des chaînes, des flottants ou d'autres objets. Toutes les clés sont converties en chaînes via toString() avant d'être ajoutées au hachage. Vous pouvez le confirmer avec un code de test:

<script>
  var array = [];
  array[0] = "zero";
  array[new Date().getTime()] = "now";
  array[3.14] = "pi";

  for (var i in array) {
      alert("array["+i+"] = " + array[i] + ", typeof("+i+") == " + typeof(i));
  }
</script>

Affiche:

array[0] = zero, typeof(0) == string
array[1254503972355] = now, typeof(1254503972355) == string
array[3.14] = pi, typeof(3.14) == string

Remarquez comment j'ai utilisé la syntaxe for...in, Qui ne vous donne que les indices réellement définis. Si vous utilisez le style d'itération for (var i = 0; i < array.length; ++i) le plus courant, vous aurez évidemment des problèmes avec les indices de tableau non standard.

62
John Kugelman

Vous pouvez éviter le problème en utilisant une syntaxe javascript conçue pour ce genre de chose. Vous pouvez le traiter comme un dictionnaire, mais la syntaxe "pour ... dans ..." vous permettra de tous les saisir.

var sparse = {}; // not []
sparse["whatever"] = "something";
10
John Fisher

Les objets Javascript sont rares et les tableaux ne sont que des objets spécialisés avec une propriété de longueur auto-entretenue (qui est en fait un plus grand que le plus grand index, pas le nombre d'éléments définis) et quelques méthodes supplémentaires. Vous êtes en sécurité de toute façon; utilisez un tableau si vous en avez besoin, c'est des fonctionnalités supplémentaires, et un objet sinon.

7
Justin Love

La réponse, comme c'est généralement le cas avec JavaScript, est "c'est un peu plus bizarre ...."

L'utilisation de la mémoire n'est pas définie et toute implémentation peut être stupide. En théorie, const a = []; a[1000000]=0; pourrait graver des mégaoctets de mémoire, tout comme const a = [];. En pratique, même Microsoft évite ces implémentations.

Justin Love souligne, l'attribut de longueur est l'ensemble d'index le plus élevé . MAIS ce n'est mis à jour que si l'index est un entier.

Ainsi, le tableau est clairsemé. MAIS les fonctions intégrées telles que Reduce (), Math.max () et "for ... of" parcourent toute la gamme d'indices entiers possibles de 0 à la longueur, en visitant beaucoup qui renvoient "indéfini". MAIS les boucles 'for ... in' peuvent faire ce que vous attendez, ne visitant que les clés définies.

Voici un exemple utilisant Node.js:

"use strict";
const print = console.log;

let a = [0, 10];
// a[2] and a[3] skipped
a[4] = 40;
a[5] = undefined;  // which counts towards setting the length
a[31.4] = 'ten pi';  // doesn't count towards setting the length
a['pi'] = 3.14;
print(`a.length= :${a.length}:, a = :${a}:`);
print(`Math.max(...a) = :${Math.max(a)}: because of 'undefined values'`);
for (let v of a) print(`v of a; v=:${v}:`);
for (let i in a) print(`i in a; i=:${i}: a[i]=${a[i]}`);

donnant:

a.length= :6:, a = :0,10,,,40,:
Math.max(...a) = :NaN: because of 'undefined values'
v of a; v=:0:
v of a; v=:10:
v of a; v=:undefined:
v of a; v=:undefined:
v of a; v=:40:
v of a; v=:undefined:
i in a; i=:0: a[i]=0
i in a; i=:1: a[i]=10
i in a; i=:4: a[i]=40
i in a; i=:5: a[i]=undefined
i in a; i=:31.4: a[i]=ten pi
i in a; i=:pi: a[i]=3.14

Mais. Il y a plus de cas d'angle avec des tableaux non encore mentionnés.

2
Charles Merriam