He observado esto en Firefox-3.5.7 / Firebug-1.5.3 y Firefox-3.6.16 / Firebug-1.6.2
Cuando enciendo Firebug:
var x = new Array(3)
console.log(x)
// [undefined, undefined, undefined]
var y = [undefined, undefined, undefined]
console.log(y)
// [undefined, undefined, undefined]
console.log( x.constructor == y.constructor) // true
console.log(
x.map(function() { return 0; })
)
// [undefined, undefined, undefined]
console.log(
y.map(function() { return 0; })
)
// [0, 0, 0]
¿Que está pasando aqui? ¿Es esto un error o no estoy entendiendo cómo usarlo new Array(3)
?
javascript
arrays
map-function
rampion
fuente
fuente
var y = x.map(function(){return 0; });
, y obtengo esto tanto para el nuevo método Array () como para la matriz literal. Probé en Firefox 4 y Chrome.Respuestas:
Parece que el primer ejemplo
Crea una matriz con punteros indefinidos.
Y el segundo crea una matriz con punteros a 3 objetos indefinidos, en este caso los punteros mismos NO están indefinidos, solo los objetos a los que apuntan.
Como el mapa se ejecuta en el contexto de los objetos en la matriz, creo que el primer mapa no puede ejecutar la función mientras que el segundo logra ejecutarse.
fuente
map
llama a una función de devolución de llamada proporcionada una vez para cada elemento de una matriz, en orden, y construye una nueva matriz a partir de los resultados.callback
Se invoca solo para los índices de la matriz que tienen valores asignados ; no se invoca para índices que se han eliminado o a los que nunca se les han asignado valores ". En este caso,x
los valores no tienen valores explícitamente asignados, mientras quey
los valores se asignaron, incluso si era el valorundefined
.(new Array(1))[0] === [undefined][0]
.hasOwnProperty
menos quehasOwnProperty
tenga un error:(new Array(1)).hasOwnProperty(0) === false
y[undefined].hasOwnProperty(0) === true
. De hecho, puede hacer exactamente lo mismo conin
:0 in [undefined] === true
y0 in new Array(0) === false
.x = new Array(3);
es equivalente ax = [,,,];
, nox = [undefined, undefined, undefined]
.Tenía una tarea que solo conocía la longitud de la matriz y necesitaba transformar los elementos. Quería hacer algo como esto:
Para crear rápidamente una matriz como esta:
Pero no funcionó porque: (vea la respuesta de Jonathan Lonowski algunas respuestas arriba)
La solución podría ser llenar los elementos de la matriz con cualquier valor (incluso con indefinido) usando Array.prototype.fill ()
Mostrar fragmento de código
Actualizar
Otra solución podría ser:
fuente
undefined
el.fill()
método, simplificando el código muy ligeramente paralet arr = new Array(10).fill().map((val,idx) => idx);
Array.from(Array(10))
¡Con ES6, puedes hacerlo
[...Array(10)].map((a, b) => a)
, rápido y fácil!fuente
new Array(10).fill()
. Mismo resultado que[...Array(10)]
[...Array(10).keys()]
Solución ES6:
Sin embargo, no funciona en mecanografiado (2.3)
fuente
Array(10).fill("").map( ...
es lo que funcionó para mí con Letra de imprenta 2.9Las matrices son diferentes. La diferencia es que
new Array(3)
crea una matriz con una longitud de tres pero sin propiedades, mientras que[undefined, undefined, undefined]
crea una matriz con una longitud de tres y tres propiedades llamadas "0", "1" y "2", cada una con un valor deundefined
. Puedes ver la diferencia usando elin
operador:Esto se debe al hecho un tanto confuso de que si intenta obtener el valor de una propiedad inexistente de cualquier objeto nativo en JavaScript, regresa
undefined
(en lugar de arrojar un error, como sucede cuando intenta hacer referencia a una variable inexistente ), que es lo mismo que obtienes si la propiedad se ha establecido explícitamente anteriormenteundefined
.fuente
Desde la página de MDC para
map
:[undefined]
en realidad aplica el setter en el (los) índice (es) para quemap
itere, mientras quenew Array(1)
solo inicializa el (los) índice (es) con un valor predeterminado deundefined
modomap
que lo omite.Creo que esto es lo mismo para todos los métodos de iteración .
fuente
En la especificación ECMAScript sexta edición.
new Array(3)
solo define propiedadeslength
y no define propiedades de índice como{length: 3}
. ver https://www.ecma-international.org/ecma-262/6.0/index.html#sec-array-len Paso 9.[undefined, undefined, undefined]
definirá propiedades de índice y propiedades de longitud como{0: undefined, 1: undefined, 2: undefined, length: 3}
. ver https://www.ecma-international.org/ecma-262/6.0/index.html#sec-runtime-semantics-arrayaccumulationElementList
Paso 5.métodos
map
,every
,some
,forEach
,slice
,reduce
,reduceRight
,filter
de array se compruebe la propiedad de índice porHasProperty
método interno, por lo quenew Array(3).map(v => 1)
no invocar la devolución de llamada.Para obtener más detalles, consulte https://www.ecma-international.org/ecma-262/6.0/index.html#sec-array.prototype.map
¿Como arreglar?
fuente
Creo que la mejor manera de explicar esto es mirar la forma en que Chrome lo maneja.
Entonces, lo que realmente está sucediendo es que el nuevo Array () está devolviendo una matriz vacía que tiene una longitud de 3, pero sin valores. Por lo tanto, cuando se ejecuta
x.map
en una matriz técnicamente vacía, no hay nada que configurar.Firefox simplemente 'llena' esas ranuras vacías
undefined
aunque no tenga valores.No creo que esto sea explícitamente un error, solo una mala forma de representar lo que está sucediendo. Supongo que Chrome es "más correcto" porque muestra que en realidad no hay nada en la matriz.
fuente
Acabo de encontrarme con esto. Seguro que sería conveniente poder usarlo
Array(n).map
.Array(3)
rinde aproximadamente{length: 3}
[undefined, undefined, undefined]
crea las propiedades numeradas:{0: undefined, 1: undefined, 2: undefined, length: 3}
.La implementación de map () solo actúa sobre propiedades definidas.
fuente
No es un error Así es como se define el constructor Array para trabajar.
De MDC:
El
.map()
método solo incluye en la iteración elementos de la matriz que tienen valores asignados explícitamente. Incluso una asignación explícita deundefined
hará que un valor se considere elegible para su inclusión en la iteración. Eso parece extraño, pero es esencialmente la diferencia entre unaundefined
propiedad explícita en un objeto y una propiedad que falta:El objeto
x
no tiene una propiedad llamada "z", y el objetoy
sí. Sin embargo, en ambos casos parece que el "valor" de la propiedad esundefined
. En una matriz, la situación es similar: el valor delength
realiza implícitamente una asignación de valor a todos los elementos desde cero hastalength - 1
. La.map()
función por lo tanto no va a hacer nada (no llamará a la devolución de llamada) cuando se le llama en una serie de nueva construcción con el constructor Array y un argumento numérico.fuente
undefined
para siempre?x = []
lugar dex = new Array()
Si está haciendo esto para llenar fácilmente una matriz con valores, no puede usar el relleno por razones de soporte del navegador y realmente no quiere hacer un ciclo for, también puede hacer lo
x = new Array(3).join(".").split(".").map(...
que le dará una matriz de vacío instrumentos de cuerda.Debo decir que es bastante feo, pero al menos el problema y la intención se comunican con bastante claridad.
fuente
Dado que la pregunta es por qué, esto tiene que ver con cómo se diseñó JS.
Hay dos razones principales que se me ocurren para explicar este comportamiento:
Rendimiento: dado
x = 10000
ynew Array(x)
es aconsejable que el constructor evite bucles de 0 a 10000 para llenar la matriz conundefined
valores.Implícitamente "indefinido": Dar
a = [undefined, undefined]
yb = new Array(2)
,a[1]
yb[1]
lo hará tanto la rentabilidadundefined
, peroa[8]
yb[8]
también regresaráundefined
incluso si están fuera de rango.En última instancia, la notación
empty x 3
es un atajo para evitar establecer y mostrar una larga lista deundefined
valores que deundefined
todos modos se deben a que no se declaran explícitamente.Nota: Dada la matriz
a = [0]
ya[9] = 9
,console.log(a)
regresará(10) [0, empty x 8, 9]
, llenando el vacío automáticamente al devolver la diferencia entre los dos valores declarados explícitamente.fuente
Por razones explicadas a fondo en otras respuestas,
Array(n).map
no funciona. Sin embargo, en ES2015Array.from
acepta una función de mapa:fuente
Aquí hay un método de utilidad simple como solución alternativa:
Mapa simple para
Ejemplo completo
Aquí hay un ejemplo más completo (con controles de cordura) que también permite especificar un índice inicial opcional:
Contando hacia atrás
Manipular el índice pasado a la devolución de llamada permite contar hacia atrás:
fuente