Es decir, si uso la hora actual como índice en la matriz:
array[Date.getTime()] = value;
¿El intérprete instanciará todos los elementos desde 0 hasta ahora? ¿Los diferentes navegadores lo hacen de manera diferente?
Recuerdo que solía haber un error en el kernel de AIX , que creaba pseudo-ttys a pedido, pero si lo hiciera, di "echo> / dev / pty10000000000", crearía / dev / pty0, / dev / pty1, .... y luego caer muerto. Fue divertido en las ferias comerciales, pero no quiero que esto les pase a mis clientes.
Respuestas:
La forma exacta en que se implementan las matrices de JavaScript difiere de un navegador a otro, pero generalmente recurren a una implementación escasa, probablemente la misma que se usa para el acceso a las propiedades de los objetos regulares, si usar una matriz real sería ineficiente.
Tendrá que pedirle a alguien con más conocimiento sobre implementaciones específicas que responda qué provoca exactamente el cambio de denso a escaso, pero su ejemplo debería ser perfectamente seguro. Si desea obtener una matriz densa, debe llamar al constructor con un argumento de longitud explícito y esperar que realmente obtenga uno.
Consulte esta respuesta para obtener una descripción más detallada de olliej.
fuente
foo = new Array(10000)
. Sin embargo, esto se supone que el trabajo:foo = Array.apply(null, {length: 10});
.Sí lo son. En realidad, son tablas hash internamente, por lo que puede usar no solo números enteros grandes, sino también cadenas, flotantes u otros objetos. Todas las claves se convierten en cadenas
toString()
antes de agregarlas al hash. Puede confirmar esto con algún código de prueba:Muestra:
Observe cómo utilicé la
for...in
sintaxis, que solo le brinda los índices que realmente están definidos. Si usa elfor (var i = 0; i < array.length; ++i)
estilo de iteración más común , obviamente tendrá problemas con índices de matriz no estándar.fuente
length
propiedad mágicalength
solo es invisible en losfor..in
bucles porque tiene laDontEnum
bandera establecida; en ES5, se llama al atributo de propiedadenumerable
y se puede establecer explícitamente a través deObject.defineProperty()
String
; cualquier otra cosa que ponga en el subíndice obtienetoString()
-ed. Combine esto con la imprecisión entera de un Número grande y significa que si establecea[9999999999999999]=1
,a[10000000000000000]
será 1 (y muchos más comportamientos sorprendentes). El uso de números no enteros como claves es muy imprudente, y los objetos arbitrarios son correctos.Puede evitar el problema utilizando una sintaxis de JavaScript diseñada para este tipo de cosas. Puede tratarlo como un diccionario, pero la sintaxis "para ... en ..." le permitirá tomarlos todos.
fuente
Los objetos de Javascript son escasos y las matrices son solo objetos especializados con una propiedad de longitud mantenida automáticamente (que en realidad es uno más grande que el índice más grande, no el número de elementos definidos) y algunos métodos adicionales. Estás a salvo de cualquier manera; use una matriz si necesita sus características adicionales y un objeto en caso contrario.
fuente
La respuesta, como suele ser cierto con JavaScript, es "es un poco más extraño ..."
El uso de memoria no está definido y se permite que cualquier implementación sea estúpida. En teoría,
const a = []; a[1000000]=0;
podría quemar megabytes de memoria, como podríaconst a = [];
. En la práctica, incluso Microsoft evita esas implementaciones.Justin Love señala que el atributo de longitud es el conjunto de índice más alto . PERO solo se actualiza si el índice es un número entero.
Entonces, la matriz es escasa. PERO funciones integradas como reduce (), Math.max () y "para ... de" recorrerán todo el rango de posibles índices enteros desde 0 hasta la longitud, visitando muchos que devuelven 'indefinido'. PERO los bucles 'for ... in' pueden hacer lo que espera, visitando solo las claves definidas.
Aquí tienes un ejemplo con Node.js:
dando:
Pero. Hay más casos de esquina con matrices aún no mencionadas.
fuente
La escasez (o densidad) se puede confirmar empíricamente para NodeJS con el process.memoryUsage () no estándar .
A veces, el nodo es lo suficientemente inteligente como para mantener la matriz escasa:
A veces, el nodo elige hacerlo denso (este comportamiento bien podría optimizarse en el futuro):
Luego, escaso de nuevo:
Entonces, tal vez usar una matriz densa para tener una idea del error original del kernel de AIX podría necesitar ser forzado con un rango similar :
Porque ¿por qué no hacerlo caer?
fuente
Pueden serlo, pero no siempre tienen que serlo, y pueden rendir mejor cuando no lo son.
Aquí hay una discusión sobre cómo probar la escasez de índices en una instancia de matriz: https://benmccormick.org/2018/06/19/code-golf-sparse-arrays/
Este código ganador de golf (menos caracteres) es:
Básicamente, recorre la matriz para las entradas indexadas mientras se disminuye el valor de longitud y se devuelve el
!!
booleano reforzado del resultado numérico falso / verdadero (si el acumulador se reduce hasta cero, el índice está completamente poblado y no escaso). Las advertencias de Charles Merriam anteriores también deben tenerse en cuenta y este código no las aborda, pero se aplican a las entradas de cadenas hash que pueden suceder al asignar elementos conarr[var]= (something)
var no era un entero.Una razón para preocuparse por la escasez de índices son sus efectos en el rendimiento, que pueden diferir entre los motores de secuencia de comandos. Aquí hay una gran discusión sobre la creación / inicialización de matrices: ¿Cuál es la diferencia entre "Array ()" y "[]" al declarar un JavaScript ¿formación?
Una respuesta reciente a esa publicación tiene un enlace a esta inmersión profunda en cómo V8 intenta optimizar las matrices etiquetándolas para evitar (volver a) probar características como la escasez: https://v8.dev/blog/elements-kinds . La publicación del blog es del 17 de septiembre y el material está sujeto a algunos cambios, pero el desglose de las implicaciones para el desarrollo diario es útil y claro.
fuente