Les index négatifs dans les tableaux JavaScript contribuent-ils à la longueur du tableau?

En javascript, je définis un tableau comme celui-ci

var arr = [1,2,3]; 

Je peux aussi faire

 arr[-1] = 4; 

Maintenant, si je le fais

 arr = undefined; 

Je perds aussi la référence à la valeur à arr [-1] .

Donc pour moi logiquement, il semble que arr [-1] soit aussi une partie de l' arr .

Mais quand je fais suite (sans configurer arr à indéfini)

 arr.length; 

Il renvoie 3 pas 4 ;

Donc, mon argument est que si les tableaux peuvent être utilisés avec des index négatifs, ces indices négatifs devraient également faire partie de leur longueur **. Je ne sais pas si je me trompe ou il me manque un concept sur les tableaux.

Donc pour moi logiquement, il semble que arr [-1] soit aussi une partie de l'arr.

Oui, mais pas comme vous le pensez.

Vous pouvez attribuer des propriétés arbitraires à un tableau (tout comme n'importe quel autre objet en JavaScript), ce que vous faites lorsque vous "indexez" le tableau à -1 et attribuez une valeur. Étant donné que ce n'est pas un membre du tableau et juste une propriété arbitraire, vous ne devriez pas attendre de la length pour considérer cette propriété.

En d'autres termes, le code suivant fait la même chose:

 ​var arr = [1, 2, 3]; ​arr.cookies = 4; alert(arr.length); 

La propriété length renverra un numéro un plus élevé que l'indice "index" le plus élevé, où Array "index" sont des nombres entiers supérieurs ou égaux à zéro. Notez que JS permet des tableaux "clairs":

 var someArray = []; someArray[10] = "whatever"; console.log(someArray.length); // "11" 

Bien sûr, s'il n'y a pas d'éléments, la length est 0 . Notez également que la length n'est pas mise à jour si vous utilisez une delete pour supprimer l'élément le plus élevé.

Mais les tableaux sont des objets, de sorte que vous pouvez assigner des propriétés avec d'autres noms de propriétés arbitraires, y compris des nombres ou des fractions négatifs:

 someArray[-1] = "A property"; someArray[3.1415] = "Vaguely Pi"; someArray["test"] = "Whatever"; 

Notez que derrière les scènes, JS convertit les noms de propriétés en chaînes même lorsque vous fournissez un nombre comme -1 . (Les index entiers positifs deviennent également des chaînes, d'ailleurs.)

Les méthodes de tableau, comme .pop() , .slice() , etc., ne fonctionnent que sur des "index" entiers zéro ou supérieur, et non sur d'autres propriétés, donc la length est cohérente sur ce point.

Si vous voulez vraiment que des index négatifs et d'autres index soient inclus dans la longueur, créez les fonctionnalités vous-même:

 function getExtendedArray() { var a = []; Object.defineProperty(a, 'totalLength', { get : function() { return Object.keys(a).length; } }); return a; } 

Ensuite, par exemple:

 var myArray = getExtendedArray(); console.log(myArray.totalLength); // 0 myArray.push("asdf"); myArray[-2] = "some string"; myArray[1.7777] = "other string"; console.log(myArray.totalLength); // 3 

Notez que lorsque vous utilisez un index de position (ou 0), les valeurs sont placées dans le tableau:

 var array = []; array[0] = "Foo"; array[1] = "Bar"; // Result: ["Foo", "Bar"] // Length: 2 

Ce n'est pas le cas lorsque vous ajoutez des valeurs non indexées (pas 0-9 +):

 var array = []; array[0] = "Foo"; array[1] = "Bar"; array[-1] = "Fizzbuzz"; // Not a proper array index - kill it // Result: ["Foo", "Bar"] // Length: 2 

Les valeurs ne sont placées que dans le tableau lorsque vous jouez selon les règles. Lorsque vous ne le faites pas, ils ne sont pas acceptés. Ils sont cependant acceptés sur l'objet Array lui-même, ce qui est le cas à peu près n'importe quoi dans JavaScript. Même si ["Foo", "Bar"] sont les seules valeurs de notre gamme, nous pouvons toujours accéder à "Fizzbuzz" :

 array[-1]; // "Fizzbuzz" 

Mais notez encore que cela ne fait pas partie des valeurs du tableau, car son «index» n'est pas valide. Il a plutôt été ajouté sur le tableau comme un autre membre. Nous pourrions avoir accès à d'autres membres du tableau de la même manière:

 array["pop"]; // function pop() { [native code] } 

Notez ici que nous accédons à la méthode pop sur le tableau, ce qui nous informe que cela contient un code natif. Nous n'acceptons aucune des valeurs de tableau avec une clé de "pop", mais plutôt un membre sur l'objet de tableau lui-même. Nous pouvons encore confirmer cela en parcourant les membres publics de l'objet:

 for (var prop in array) console.log(prop, array[prop]); 

Ce qui supprime ce qui suit:

  0 Foo 1 Bar -1 Fizzbuzz 

Donc encore, c'est sur l' objet , mais ce n'est pas dans le tableau .

Superbe question! Je me suis fait réussi à faire une double prise.

Les tableaux en JavaScript sont en fait des objets. Ils sont simplement prototypes du constructeur Array.

Les indices de matrice sont en fait des clés dans un hashmap, et toutes les clés sont converties en chaînes. Vous pouvez créer n'importe quelle clé (c.-à-d. "-1"), mais les méthodes sur Array sont conçues pour agir comme un tableau. La length n'est donc pas la taille de l'objet, mais elle n'est plus garantie que pour être plus grande que l'indice entier le plus élevé. De même, l'impression arr ne liste que les valeurs avec les touches entières> = 0.

Plus d'infos ici.

Selon MDN:

La valeur de la propriété length est un nombre entier avec un signe positif et une valeur inférieure à 2 à la puissance 32 (232)

En Javascript, vous pouvez définir une propriété sur tout objet que vous créez.

 var array = new Array(); array = [1,2,3]; array["boom"] = "pow"; 

De la même manière, lorsque vous définissez un indice négatif, il l'enregistre comme une propriété sur le tableau plutôt qu'une partie de l'indice.

 array[-1] = "property does not add to array length"; 

C'est pourquoi la longueur ne le reflète pas, mais une boucle for..in le montre.

Lorsque vous utilisez des index non positifs ou non numériques, le tableau se comporte comme un tableau associatif qui possède des paires de valeurs-clés.

Pour itérer à travers le tableau, vous pouvez utiliser

 for(var index in myArray) { document.write( index + " : " + myArray[index] + "<br />"); }