2011-06-27 19 views
21

Tengo la siguiente situación:¿Ocupa memoria null en javascript?

var large = [a,b,c,d,e,f,g,h,i]; 
var small = [a2, b2, c2, null, null, null, null, null, null, i2]; 

, donde todos los elementos de ambas matrices es un objeto.

La pequeña matriz contiene información relacionada con la más grande, pero no todos los elementos de large requieren un elemento asociado en small y entonces lo configuré en null. Sin embargo, todavía necesito mantener los índices iguales para poder hacer cosas como large[16].id + ': ' + small[16].description. ¿El hecho de que tengo una matriz que es en su mayoría null en valor resulta en un mayor uso de memoria?

Mi pregunta es si sería mejor hacer algo como small = [a2,b2,c2,i2], y establecer índices en propiedades como a2.index = 0; b2.index = 1 y así sucesivamente.

También he encontrado una sugerencia para utilizar indefinido en su lugar y alguien incluso mencionó la implementación de listas vinculadas. No creo que deba implementar una lista vinculada, ya que no agrego ni elimino elementos muy a menudo.

Respuesta

14

Las matrices son en realidad objetos con un tratamiento especial de propiedades con nombres que son índices de matriz.

Al asignar 'null', usted trae a la existencia cada propiedad, que utilizará una cantidad de memoria distinta de cero y, como ya se mencionó, ralentizará las búsquedas.

Puede eludir los miembros inexistentes en su lugar, lo que se traducirá en una matriz dispersa:

var small = [a2, b2, c2,,,,,,, i2]; 
// small == [a2, b2, c2,undefined,undefined,undefined,undefined,undefined,undefined, i2] 

Editar Tenga en cuenta que undefinedhace toma el espacio si asigna explícitamente a un elemento de matriz (o cualquier variable). Para reclamar memoria en este caso, necesitará explícitamente delete el elemento. El estilo de inicialización que se muestra en mi ejemplo de código nunca asigna nada a los elementos elided, por lo que no existen en absoluto. Esto se puede confirmar mediante la comprobación de la existencia aquellos elementos como propiedades del objeto de matriz:

// continued from above 
small.hasOwnProperty('3'); // returns false 

small[3] = undefined; 
small.hasOwnProperty('3'); // now returns true because the property exists 

delete small[3]; 
small.hasOwnProperty('3'); // returns false again 

alert(small.length); // alerts '10', showing that the array itself is still intact. 
+0

Esta sería mi sugerencia también. –

+0

Tenga en cuenta que el hecho de establecer una propiedad en indefinido no hace que ocupe espacio: una propiedad puede existir y tener un valor explícito de "indefinido", por ejemplo, 'var x = {a: undefined}; alerta (x.a); alerta (x.b); alerta (a en x); alerta (b en x); '. Si desea eliminar una propiedad, use 'delete'. – gsnedders

+0

Gracias por mencionarlo. Quería mencionarlo, y editaré la respuesta para incluirla. – codelahoma

1

¿Por qué no simplemente poner los artículos pequeños en grande [2] .small? De todos modos, generalmente no tiene que preocuparse por el consumo de memoria en javascript, pero aún así es mejor dejar las posiciones no utilizadas en un formato indefinido pequeño (que es algo más que establecerlas en indefinido), para que el motor de JavaScript pueda decidir cambiar a la matriz dispersa (representada por una tabla hash en lugar de una matriz).

1

No puedo responder completamente a su pregunta, porque no estoy seguro de si null ocupa tanto espacio como establecerlo explícitamente en undefined. Pero creo que la manera estándar de hacer esto es utilizar el Array constructor:

var large = [1,2,3,4,5,6,7]; 
var small = new Array(large.length); 
small.length; // 7 
small[0]; // undefined 

Creo que esto usa menos memoria que definir valores explícitamente a indefinido, aunque el efecto es el mismo. Lo he usado para una matriz dispersa con más de 250,000 índices, y no tuve problemas de memoria (usando Google Chrome).

Editar: (después de jugar un rato y hacer un poco más investigación) Mucha gente no le gusta el constructor new Array(), por muchas razones (véase, por ejemplo this discussion). Pero creo que tiene un par de ventajas para las matrices grandes y dispersas:

  • establece la propiedad length correctamente. Si necesita la longitud de la matriz para que coincida con su matriz grande, no puede hacer esto de otra manera sin configurarlo explícitamente (small.length = large.length) o poner algo indefinido al final (small[large.length-1] = undefined).

  • No establece claves para índices vacíos, lo que me lleva a pensar que usa menos memoria. Si tiene una matriz a = [null,null,null] o a = [undefined,undefined,undefined], esas matrices tienen tres índices, y si usa a.map o a.forEach, se llamará a su función para cada índice. Si usa a = new Array(3) y luego llama al a.forEach, se llamará a su función solo para los índices que ha establecido explícitamente en un valor posterior a la construcción.

Pero no parece ser una gran diferencia de rendimiento entre:

var a = new Array(2000); 
a[2000] = 1; 

y:

var = []; 
a[2000] = 1; 

cuales también le da una matriz de longitud 2000 con solo un índice definido. Así que si no le importa si el length de small coincide con el length de large, sólo haría uso de var a = [] y tienen que cambiar de tamaño dinámicamente según sea necesario - desde la perspectiva sencilla de establecer y obtener valores en los índices específicos, es exactamente el mismo.

1

nulo consumirá la memoria sólo por el tamaño de una palabra 'NULL' (en términos de intérprete), pero la búsqueda será más lento debido a la matriz abrumado con objetos que no irá al resultado de la búsqueda, y JS no tiene una forma de optimizar esto. Debería usar mejor la matriz de objetos, y cada objeto debería mantener un valor y el índice.

El uso de undefined es complicado también. En términos de interpretación y tamaño de script, esto aumentará la memoria, pero esto no forma parte de las especificaciones para indicar si el valor indefinido debería consumir memoria y cuánto, por lo que depende de un navegador, sus instalaciones recogen la basura, consumen un montón de memoria. etc. La mejor manera de hacerlo es intentarlo, probablemente. Ejecute una matriz relativamente grande de NULLs y undefined dentro de Chrome, tome una instantánea de montón y compare.

+2

La especificación requiere que 'undefined' ser devuelto por la función interna' GetOwnProperty' de un objeto si el objeto no tiene ninguna propiedad por el especificado nombre. Mientras que el valor real 'undefined' * que usaría, por ejemplo, en un condicional puede usar memoria, * propiedades indefinidas * (que es lo que un elemento de matriz al que nunca se le ha asignado un valor) no lo hace. – codelahoma

Cuestiones relacionadas