La mayoría de los tutoriales que he leído en matrices en JavaScript (incluidos w3schools y devguru ) sugieren que puede inicializar una matriz con una cierta longitud pasando un número entero al constructor de matrices utilizando la var test = new Array(4);
sintaxis.
Después de usar esta sintaxis generosamente en mis archivos js, ejecuté uno de los archivos a través de jsLint , y se asustó:
Error: Problema en la línea 1, carácter 22: Se esperaba ')' y en su lugar vio '4'.
prueba var = nueva matriz (4);
Problema en la línea 1, carácter 23: Se esperaba ';' y en su lugar vi ')'.
prueba var = nueva matriz (4);
Problema en la línea 1, carácter 23: esperaba un identificador y en su lugar vio ')'.
Después de leer la explicación de jsLint de su comportamiento , parece que a jsLint realmente no le gusta la new Array()
sintaxis y, en cambio, prefiere []
al declarar matrices.
Entonces tengo un par de preguntas:
Primero, ¿por qué? ¿Corro algún riesgo al utilizar la new Array()
sintaxis? ¿Hay incompatibilidades del navegador que debo tener en cuenta?
Y segundo, si cambio a la sintaxis de corchetes, ¿hay alguna forma de declarar una matriz y establecer su longitud en una sola línea, o tengo que hacer algo como esto:
var test = [];
test.length = 4;
fuente
new Array()
en general, pero está bien con la especificación de tamaño. Creo que todo se reduce a la consistencia del código en todo el contexto.Respuestas:
¿Por qué quieres inicializar la longitud? Teóricamente no hay necesidad de esto. Incluso puede dar lugar a un comportamiento confuso, porque todas las pruebas que usan el
length
para averiguar si una matriz está vacía o no informarán que la matriz no está vacía.Algunas pruebas muestran que establecer la longitud inicial de las matrices grandes puede ser más eficiente si la matriz se llena después, pero la ganancia de rendimiento (si la hay) parece diferir de un navegador a otro.
A jsLint no le gusta
new Array()
porque el constructor es ambiguo.crea una matriz vacía de longitud 4. Pero
crea una matriz que contiene el valor
'4'
.Con respecto a su comentario: en JS no necesita inicializar la longitud de la matriz. Crece dinámicamente. Puede almacenar la longitud en alguna variable, p. Ej.
fuente
for
bucle que itera a lo largo de la matriz y lo llena. Supongo que habría otras formas de hacer esto en JavaScript, por lo que la respuesta real a "¿Por qué quiero hacer esto?" es "Debido a los viejos hábitos que se formaron durante la programación en otros lenguajes". :)new Array(10)
no crea una matriz con 10 elementos indefinidos. Simplemente crea una matriz vacía con una longitud de 10. Vea esta respuesta para la desagradable verdad: stackoverflow.com/questions/18947892/…Array(5)
le da una matriz con longitud 5 pero sin valores, por lo tanto, no puede iterar sobre ella.Array.apply(null, Array(5)).map(function () {})
le ofrece una matriz con longitud 5 e indefinida como valores, ahora se puede repetir.Array.apply(null, Array(5)).map(function (x, i) { return i; })
le da una matriz con longitud 5 y valores 0,1,2,3,4.Array(5).forEach(alert)
no hace nada,Array.apply(null, Array(5)).forEach(alert)
te da 5 alertasES6
nos daArray.from
así que ahora también puedes usarArray.from(Array(5)).forEach(alert)
Si desea inicializar con un cierto valor, es bueno saberlo ...
Array.from('abcde')
,Array.from('x'.repeat(5))
o
Array.from({length: 5}, (v, i) => i) // gives [0, 1, 2, 3, 4]
fuente
Array
recibe múltiples argumentos, itera sobre elarguments
objeto y aplica explícitamente cada valor a la nueva matriz. Cuando llameArray.apply
con una matriz o un objeto con una propiedad de longitud,Array
usará la longitud para establecer explícitamente cada valor de la nueva matriz. Es por eso queArray(5)
da una matriz de 5 elisiones, mientras queArray.apply(null, Array(5))
da una matriz de 5 indefinidos. Para más información, vea esta respuesta.Array.apply(null, Array(5))
también se puede escribir comoArray.apply(null, {length: 5})
. Realmente no hay mucha diferencia, pero este último es inequívocamente claro que la intención es crear una matriz delength 5
, y no una matriz que contenga5
Con ES2015
.fill()
ahora puede simplemente hacer:Lo cual es mucho más conciso que
Array.apply(0, new Array(n)).map(i => value)
Es posible dejar caer el
0
en.fill()
y ejecutar sin argumentos, que va a llenar la matriz conundefined
. ( Sin embargo, esto fallará en Typecript )fuente
When Array is called as a function rather than as a constructor, it also creates and initializes a new Array object. Thus the function call Array(…) is equivalent to the object creation expression new Array(…) with the same arguments
Array(n).fill()
O
Nota: no puede hacer bucles de espacios vacíos, es decir
Array(4).forEach(() => …)
O
( mecanografiado seguro )
O
Método clásico que utiliza una función (funciona en cualquier navegador)
Crear matrices anidadas
Al crear una matriz 2D con la
fill
intuitiva debe crear nuevas instancias. Pero lo que realmente sucederá es que la misma matriz se almacenará como referencia.Solución
Entonces, una matriz 3x2 se verá así:
Matriz N-dimensional
Inicializa un tablero de ajedrez
fuente
a[0].push(9);
// [ [6, 9], [6], [6] ]
debería deberse aa[0].push(9);
// [ [6, 9], [6, 9], [6, 9] ]
que cada matriz anidada se almacena como referencia, por lo que mutar una matriz afecta al resto. Puede que lo hayas escrito mal aunque creo :)El más corto:
fuente
[
sin usar un;
ya que intentará desreferenciar la línea de arriba. Entonces, una forma segura de usar esta línea de manera predecible en cualquier parte del código sería:;[...Array(1000)]//.whateverOpsNeeded()
[...Array(5)].map((item, index) => ({ index }))
intente esto también:[...Array(5)]; console.log('hello');
const a = 'a'
y la siguiente línea[...Array(5)].//irrelevent
. ¿A qué crees que se resolvería la primera línea? Seríaconst a = 'a'[...Array(5)]
lo que resultaría en:Uncaught SyntaxError: Unexpected token ...
const a = 'a'
será un error de pelusa en ese caso. De todos modos, realmente no tiene nada que ver con esta respuesta.ES6 presenta lo
Array.from
que le permite crear un objetoArray
desde cualquier objeto "tipo matriz" o iterable :En este caso
{length: 10}
representa la definición mínima de un objeto "tipo matriz" : un objeto vacío con solo unalength
propiedad definida.Array.from
permite un segundo argumento para mapear sobre la matriz resultante.fuente
Esto inicializará la propiedad de longitud a 4:
fuente
var size = 42; var myArray = eval("["+",".repeat(size)+"]");
? (No es tan grave;)Me sorprende que no se haya sugerido una solución funcional que le permita establecer la longitud en una línea. Lo siguiente se basa en UnderscoreJS:
Por las razones mencionadas anteriormente, evitaría hacer esto a menos que quisiera inicializar la matriz a un valor específico. Es interesante observar que hay otras bibliotecas que implementan el rango, incluidos Lo-dash y Lazy, que pueden tener diferentes características de rendimiento.
fuente
Por favor, la gente todavía no abandona tus viejos hábitos. Hay una gran diferencia en la velocidad entre asignar memoria una vez y luego trabajar con las entradas en esa matriz (como antes), y asignarla muchas veces a medida que crece una matriz (que es inevitablemente lo que el sistema hace bajo el capó con otros métodos sugeridos) .
Nada de esto importa, por supuesto, hasta que desee hacer algo genial con matrices más grandes. Entonces lo hace.
Al ver que todavía no parece haber ninguna opción en JS en este momento para establecer la capacidad inicial de una matriz, utilizo lo siguiente ...
Hay compensaciones involucradas:
standard
matriz reserva permanentemente tanto espacio como la matriz más grande que haya solicitado.Pero si encaja con lo que estás haciendo, puede haber una recompensa. Puestos informales de tiempo
a bastante velocidad (unos 50 ms para el 10000 dado que con n = 1000000 tardó unos 5 segundos), y
más de un minuto (aproximadamente 90 segundos para el 10000 en la misma consola de Chrome, o aproximadamente 2000 veces más lento). Esa no solo será la asignación, sino también los 10000 empujes, bucles, etc.
fuente
(esto probablemente fue mejor como comentario, pero se hizo demasiado largo)
Entonces, después de leer esto, tenía curiosidad por saber si la preasignación era realmente más rápida, porque en teoría debería serlo. Sin embargo, este blog dio algunos consejos que lo desaconsejan http://www.html5rocks.com/en/tutorials/speed/v8/ .
Así que todavía no estoy seguro, lo puse a prueba. Y resulta que, de hecho, parece ser más lento.
Este código produce lo siguiente después de algunas ejecuciones ocasionales:
fuente
fuente
[5: 0]
esta es una matriz dispersa y probablemente no sea lo que se desea.Aquí hay otra solución
El primer argumento de
apply()
es un enlace de este objeto, que no nos importa aquí, así que lo configuramos ennull
.Array.apply(..)
llama a laArray(..)
función y extiende el{ length: 3 }
valor del objeto como sus argumentos.fuente
new Array(n)
para inicializar una matriz como estanew Array(n).map(function(notUsed,index){...})
, pero con este enfoque, como mencionó @zangw, puede hacerlo. +1 de mi parteEl constructor de matrices tiene una sintaxis ambigua , y JSLint solo hiere tus sentimientos después de todo.
Además, su código de ejemplo está roto, la segunda
var
instrucción generará unSyntaxError
. Estás configurando la propiedadlength
de la matriztest
, por lo que no hay necesidad de otravar
.En cuanto a sus opciones,
array.length
es la única "limpia". La pregunta es, ¿por qué necesita establecer el tamaño en primer lugar? Intenta refactorizar tu código para deshacerte de esa dependencia.fuente
var test
. Esa fue una copia descuidada y pegado de mi parte.Suponiendo que la longitud de la matriz es constante. En Javascript, esto es lo que hacemos:
const intialArray = new Array(specify the value);
fuente
Como se explicó anteriormente, el uso
new Array(size)
es algo peligroso. En lugar de usarlo directamente, colóquelo dentro de una "función creadora de matriz". Puede asegurarse fácilmente de que esta función esté libre de errores y evitar el peligro de llamarnew Array(size)
directamente. Además, puede darle un valor inicial predeterminado opcional. EstacreateArray
función hace exactamente eso:fuente
En la mayoría de las respuestas se recomienda a
fill
la matriz porque de lo contrario "no se puede iterar sobre ella" , pero esto no es cierto. Puede iterar una matriz vacía, pero no conforEach
. Mientras que los bucles, for of y for i loops funcionan bien.No funciona.
Estos trabajan:
Mira este violín con los ejemplos anteriores.
También los angulares
*ngFor
funcionan bien con una matriz vacía:fuente
Puede establecer la longitud de la matriz usando
array.length = youValue
Entonces sería
fuente
new Array
Este código demuestra la razón por la que no debe usar :Algún otro código podría interferir con la variable Array. Sé que es un poco descabellado que alguien escriba ese código, pero aún así ...
Además, como dijo Felix King, la interfaz es un poco inconsistente y podría generar algunos errores muy difíciles de rastrear.
Si desea una matriz con longitud = x, llena de indefinido (como
new Array(x)
lo haría), podría hacer esto:fuente
alert
yundefined
, porque algún otro código podría interferir con ellos. El segundo ejemplo es menos legible quenew Array(4)
, y no te da el mismo resultado: jsfiddle.net/73fKd