JavaScript "nueva matriz (n)" y " Matriz.prototipo.mapa " rareza
He observado esto en Firefox 3.5.7/Firebug-1.5.3 y Firefox 3.6.16/Firebug-1.6.2
Cuando enciendo 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]
¿Qué está pasando aquí? ¿Es esto un error, o estoy malinterpretando cómo usar new Array(3)
?
12 answers
Parece que el primer ejemplo
x = new Array(3);
Crea una matriz con punteros indefinidos.
Y el segundo crea una matriz con punteros a 3 objetos indefinidos, en este caso los punteros ellos mismos NO son indefinidos, solo los objetos a los que apuntan.
y = [undefined, undefined, undefined]
// The following is not equivalent to the above, it's the same as new Array(3)
y = [,,,];
Como map se ejecuta en el contexto de los objetos de la matriz, creo que el primer map no puede ejecutar la función mientras que el segundo se las arregla para ejecutarse.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-11-22 13:02:38
Tenía una tarea que solo sabía la longitud de la matriz y necesitaba transformar los elementos. Quería hacer algo como esto:
let arr = new Array(10).map((val,idx) => idx);
Para crear rápidamente una matriz como esta:
[0,1,2,3,4,5,6,7,8,9]
Pero no funcionó porque: ver 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) utilizando Array.prototipo.llenar()
let arr = new Array(10).fill(undefined).map((val,idx) => idx);
console.log(new Array(10).fill(undefined).map((val, idx) => idx));
Actualización
Otra solución podría ser:
let arr = Array.apply(null, Array(10)).map((val, idx) => idx);
console.log(Array.apply(null, Array(10)).map((val, idx) => idx));
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-10-03 07:23:29
Con ES6, usted puede hacer [...Array(10)].map((a, b) => a)
, rápido y fácil!
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-10-05 16:20:16
Los arrays 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 de undefined
. Puedes ver la diferencia usando el operador in
:
"0" in new Array(3); // false
"0" in [undefined, undefined, undefined]; // true
Esto se debe al hecho ligeramente confuso de que si intenta obtener el valor de una propiedad inexistente de cualquier objeto nativo en JavaScript, devuelve undefined
(en lugar de lanzar un error, como ocurre cuando se intenta hacer referencia a una variable inexistente), que es lo mismo que lo que se obtiene si la propiedad se ha establecido explícitamente previamente a undefined
.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-03-31 15:12:42
De la página MDC para map
:
[...]
callback
se invoca solo para los índices de la matriz que tienen un valor asignado; [...]
[undefined]
en realidad aplica el setter en el índice(es) para que map
itere, mientras que new Array(1)
solo inicializa el índice(es) con un valor predeterminado de undefined
para que map
lo omita.
Creo que esto es lo mismo para todos los métodos de iteración.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-03-31 14:47:10
Solución ES6:
[...Array(10)]
No funciona en typescript (2.3), aunque
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-05 06:22:51
Creo que la mejor manera de explicar esto es mirar la forma en que Chrome lo maneja.
>>> x = new Array(3)
[]
>>> x.length
3
Así que lo que realmente está sucediendo es que new Array() está devolviendo un array vacío que tiene una longitud de 3, pero sin valores. Por lo tanto, cuando se ejecuta x.map
en un técnicamente matriz vacía, no hay nada que establecer.
Firefox solo 'llena' esos espacios vacíos con undefined
a pesar de que no tiene valores.
No creo que esto sea explícitamente un error, solo una mala manera de representando lo que está pasando. Supongo que Chrome es" más correcto", ya que muestra que en realidad no hay nada en la matriz.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-03-31 18:26:00
En la especificación de ECMAScript 6th edition.
new Array(3)
solo defina la propiedad length
y no defina propiedades de índice como {length: 3}
. véase 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}
. véase https://www.ecma-international.org/ecma-262/6.0/index.html#sec-runtime-semantics-arrayaccumulation ElementList
Paso 5.
Métodos map
, every
, some
, forEach
, slice
, reduce
, reduceRight
, filter
of Array comprobará la propiedad index mediante el método interno HasProperty
, por lo que new Array(3).map(v => 1)
no invocará la devolución de llamada.
Para más detalles, ver https://www.ecma-international.org/ecma-262/6.0/index.html#sec-array.prototype.map
¿Cómo arreglar?
let a = new Array(3);
a.join('.').split('.').map(v => 1);
let a = new Array(3);
a.fill(1);
let a = new Array(3);
a.fill(undefined).map(v => 1);
let a = new Array(3);
[...a].map(v => 1);
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-05 06:10:00
Acabo de encontrarme con esto. Seguramente sería conveniente poder usar 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.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-10-29 02:01:55
No es un error. Así es como se define el constructor de matriz para trabajar.
De MDC:
Cuando se especifica un único parámetro numérico con el constructor de matriz, se especifica la longitud inicial de la matriz. El siguiente código crea una matriz de cinco elementos:
var billingMethod = new Array(5);
El comportamiento del constructor de matriz depende de si el parámetro único es un número.
El método .map()
solo incluye en la iteración elementos de la matriz a la que se han asignado valores explícitamente. Incluso una asignación explícita de undefined
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 una propiedad explícita undefined
en un objeto y una propiedad faltante:
var x = { }, y = { z: undefined };
if (x.z === y.z) // true
El objeto x
no tiene una propiedad llamada "z", y el objeto y
hace. Sin embargo, en ambos casos parece que el "valor" de la propiedad es undefined
. En una matriz, la situación es similar: el valor de length
realiza implícitamente una asignación de valor a todos los elementos desde cero hasta length - 1
. Por lo tanto, la función .map()
no hará nada (no llamará a la devolución de llamada) cuando se llame a una matriz recién construida con el constructor de matriz y un argumento numérico.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-02-18 15:18:03
Si está haciendo esto para llenar fácilmente una matriz con valores, no puede usar fill por razones de soporte del navegador y realmente no desea hacer un bucle for, también puede hacer x = new Array(3).join(".").split(".").map(...
que le dará una matriz de cadenas vacías.
Bastante feo tengo que decir, pero al menos el problema y la intención se comunican con bastante claridad.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-03-21 14:42:49
En Chrome, si lo hago new Array(3)
obtengo []
, así que mi conjetura es que te has encontrado con un error en el navegador.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-03-31 14:43:07