JavaScript “new Array(n)” et “Tableau.le prototype.carte” étrangeté
J'ai observé cela dans Firefox 3.5.7/Firebug-1.5.3 et Firefox 3.6.16/Firebug-1.6.2
Quand j'ai le feu jusqu'à Firebug:
>>> x = new Array(3)
[undefined, undefined, undefined]
>>> y = [undefined, undefined, undefined]
[undefined, undefined, undefined]
>>> x.constructor == y.constructor
true
>>> x.map(function(){ return 0; })
[undefined, undefined, undefined]
>>> y.map(function(){ return 0; })
[0, 0, 0]
Ce qui se passe ici? Est-ce un bug, ou suis-je l'incompréhension comment utiliser new Array(3)
?
- Je n'ai pas les mêmes résultats que vous voyez à partir de la matrice de notation littérale. Je reçois toujours pas défini au lieu de 0. Je ne reçois que des 0 résultat si j'ai mis quelque chose comme
var y = x.map(function(){return 0; });
, et j'obtiens ceci pour les new Array() la méthode et le littéral de tableau. Je l'ai testé dans Firefox 4 et Chrome.
Vous devez vous connecter pour publier un commentaire.
Il semble que le premier exemple
Crée un tableau avec undefined pointeurs.
Et le second crée un tableau avec des pointeurs vers 3 indéfini d'objets, dans ce cas, les pointeurs eux-même ne sont PAS non défini, seuls les objets qu'ils pointent.
Que la carte est exécuté dans le contexte des objets dans le tableau, je crois que la première carte ne peut pas exécuter la fonction tandis que le second parvient à exécuter.
map
appelle une fonction de rappel fourni une fois pour chaque élément dans un tableau, dans l'ordre, et construit un nouveau tableau à partir des résultats.callback
n'est invoquée que pour les index de la table qui ont attribué des valeurs; il n'est pas invoquée pour des indices qui ont été supprimés ou qui n'ont jamais été affectées des valeurs." Dans ce cas,x
's les valeurs n'ont pas explicitement les valeurs assignées, alors quey
's ont été affectés, même si c'est la valeurundefined
.(new Array(1))[0] === [undefined][0]
.hasOwnProperty
saufhasOwnProperty
lui-même a un bug:(new Array(1)).hasOwnProperty(0) === false
et[undefined].hasOwnProperty(0) === true
. En fait, vous pouvez faire exactement la même avecin
:0 in [undefined] === true
et0 in new Array(0) === false
.x = new Array(3);
est équivalent àx = [,,,];
, pasx = [undefined, undefined, undefined]
.J'ai eu une tâche que je ne connaissais que la longueur du tableau et qui sont nécessaires pour transformer les éléments.
Je voulais faire quelque chose comme ceci:
Pour créer rapidement un tableau comme ceci:
Mais il n'a pas travaillé parce que:
voir Jonathan Lonowski de répondre à quelques réponses supérieure.
Solution pourrait être de remplir les éléments de tableau avec une valeur quelconque (même avec undefined) à l'aide de Tableau.le prototype.fill()
JS:
Mise à jour
Une autre solution pourrait être:
JS:
undefined
dans le.fill()
méthode, la simplification du code très légèrement àlet arr = new Array(10).fill().map((val,idx) => idx);
Avec ES6, vous pouvez le faire
[...Array(10)].map((a, b) => a)
, rapide et facile!new Array(10).fill()
. Même résultat que[...Array(10)]
ES6 solution:
Ne fonctionne pas sur la machine (2.3), bien que
Array(10).fill("").map( ...
est ce qui a fonctionné pour moi avec Tapuscrit de 2,9Les tableaux sont différents. La différence est que
new Array(3)
crée un tableau avec une longueur de trois, mais pas de propriétés, tandis que[undefined, undefined, undefined]
crée un tableau avec une longueur de trois et de trois propriétés appelée "0", "1" et "2", chacune avec une valeur deundefined
. Vous pouvez voir la différence à l'aide de lain
opérateur:Cela provient de la légèrement à confusion fait que si vous essayez d'obtenir la valeur d'une propriété qui n'existe pas du tout natif objet en JavaScript, il retourne
undefined
(plutôt que de jeter une erreur, comme il arrive quand vous essayez de consulter un inexistante variable), qui est le même que ce que vous obtenez si le bien a déjà été explicitement définie àundefined
.De la MDC page pour
map
:[undefined]
s'applique en fait le setter de l'index(es), de sorte quemap
va se répéter, alors quenew Array(1)
juste initialise l'index(es) avec une valeur par défaut deundefined
doncmap
l'ignore.Je crois que c'est la même pour tous les itération méthodes.
Je pense que la meilleure façon d'expliquer cela est de regarder la façon Chrome poignées de il.
Donc ce qui se passe réellement est que new Array() retourne un tableau vide qui a une longueur de 3, mais pas de valeurs. Par conséquent, lorsque vous exécutez
x.map
sur un techniquement tableau vide, il n'y a rien à régler.Firefox juste "remplit" de ces logements vides avec
undefined
même si elle n'a pas de valeurs.Je ne pense pas que cela soit explicitement un bug, juste une mauvaise façon de représenter ce qui se passe. Je suppose que google Chrome est "plus correct", car il montre qu'il n'y a pas réellement de quoi que ce soit dans la matrice.
Dans ECMAScript 6e édition de la spécification.
new Array(3)
seulement de définir la propriétélength
et de ne pas définir les propriétés de l'index comme{length: 3}
. voir https://www.ecma-international.org/ecma-262/6.0/index.html#sec-array-len l'Étape 9.[undefined, undefined, undefined]
permettra de définir les propriétés de l'index et de la longueur de la propriété comme{0: undefined, 1: undefined, 2: undefined, length: 3}
. voir https://www.ecma-international.org/ecma-262/6.0/index.html#sec-runtime-semantics-arrayaccumulationElementList
l'Étape 5.méthodes
map
,every
,some
,forEach
,slice
,reduce
,reduceRight
,filter
de la Matrice de vérification de la propriété index parHasProperty
méthode interne, de sortenew Array(3).map(v => 1)
ne va pas appeler la fonction de rappel.pour plus de détails, voir https://www.ecma-international.org/ecma-262/6.0/index.html#sec-array.prototype.map
Comment réparer?
Viens de tomber sur cette. C'est sûr qu'il serait pratique de pouvoir utiliser
Array(n).map
.Array(3)
des rendements d'environ{length: 3}
[undefined, undefined, undefined]
crée numérotées propriétés:{0: undefined, 1: undefined, 2: undefined, length: 3}
.La carte() seulement la mise en œuvre des actes sur les propriétés définies.
Pas un bug. C'est ainsi que le constructeur Array est défini à travailler.
De MDC:
La
.map()
méthode inclut uniquement dans l'itération éléments du tableau qui ont explicitement avaient des valeurs assignées. Même explicitement la cession deundefined
va provoquer une valeur pour être admissible à l'inclusion dans l'itération. Cela semble étrange, mais c'est essentiellement la différence entre un expliciteundefined
propriété sur un objet et un manque de propriété:L'objet
x
n'est pas une propriété appelée "z", et l'objety
n'. Toutefois, dans les deux cas, il semble que la "valeur" de la propriété estundefined
. Dans un tableau, la situation est similaire: la valeur delength
ne implicitement effectuer une affectation de valeur à tous les éléments à partir de zéro parlength - 1
. Le.map()
fonction ne sera donc pas faire n'importe quoi (ne pas appeler le callback) lorsqu'elle est appelée sur un tableau nouvellement construit avec le constructeur Array et un argument numérique.undefined
pour toujours?x = []
au lieu dex = new Array()
Si vous le faites dans le but de facilement remplir un tableau avec des valeurs, ne peut pas utiliser remplir pour la prise en charge du navigateur raisons et ne veux vraiment pas faire une boucle for, vous pouvez également faire
x = new Array(3).join(".").split(".").map(...
qui vous donnera un tableau de chaînes vides.Assez moche je dois dire, mais au moins le problème et l'intention sont assez clairement communiqués.
Voici un utilitaire simple méthode comme une solution de contournement:
Simple mapFor
JS:
Exemple Complet
Voici un exemple plus complet (avec des contrôles d'intégrité) qui permet également de spécifier une option de l'indice de départ:
JS:
Le Compte À Rebours
La manipulation de l'index transmis à la fonction de rappel permet un comptage à rebours:
En Chrome, si je ne
new Array(3)
- je obtenir[]
, donc je suppose que vous avez rencontré un bug lié au navigateur.new Array(3)
résultat dans un tableau vide?new Array(3)
dans la console retourne[]
, ce qui n'est pas un résultat utile. Cependant, il n'est également de retour3
pournew Array(3).length
.length
propriété de la matrice devrait être de 3. S'agit-il?