2012-02-10 24 views
18

La diferencia entre un javascript Array y Object no es muy grande. De hecho, parece Array añade principalmente el campo length, por lo que se puede utilizar tanto Array s y Object s como matrices numéricas:¿Las matrices de JavaScript realmente se implementan como matrices?

var ar = new Array(); 
ar[0] = "foo"; 
ar["bar"] = "foo"; 

var ob = new Object(); 
ob[0] = "foo"; 
ob["bar"] = "foo"; 

assert(ar[0] == ob[0] == ar["0"] == ob["0"] == ar.bar == ob.bar); // Should be true. 

Así que mis preguntas es, en los motores de Javascript populares (V8, JavaScriptCore, SpiderMonkey, etc.), ¿cómo se maneja esto? ¡Obviamente no queremos que nuestras matrices se almacenen realmente como mapas hash con valores clave! ¿Cómo podemos estar razonablemente seguros de que nuestros datos se almacenan como una matriz real?

Por lo que yo puedo ver, hay algunos enfoques motores podría tomar:

  1. Array se implementa exactamente de la misma manera que Object - como una matriz asociativa con claves de cadena.
  2. Array es un caso especial, con una gama -como std::vector copias de las teclas numéricas, y algunos heurística densidad para evitar el uso de memoria loco si lo hace ar[100000000] = 0;
  3. Array es lo mismo que Object, y todos caen objetos en una heurística de ver si usar una matriz tendría más sentido.
  4. Algo increíblemente complicado en el que no había pensado.

Realmente esto sería más sencillo si hubiera un tipo de matriz adecuada (tos WebGL matrices mecanografiadas la tos).

+2

Este [artículo] (http://news.qooxdoo.org/javascript-array-performance-oddities-characteristics) es un poco antiguo, y no explica explícitamente la implementación. Sin embargo, realiza mediciones de rendimiento detalladas e infiere las implementaciones probables. –

+2

La matriz no es _sólo_ un mapa con una propiedad 'length' añadida. Si lo fuera, entonces cambiar o no cambiar rompería la indexación (es decircambiar un valor de una matriz, y todavía comienza en el índice 0, no 1). Así que hay al menos un poco más pasando. (No es que esto necesariamente diga nada sobre la implementación, por supuesto) – Flambino

+1

¿Por qué esperaría 'r [0] == ob [0] == ar [" 0 "] == ob [" 0 "] == ar. bar == ob.bar' para ser cierto? ''a '==' a '==' a'' es falso porque evalúa' verdadero == 'a'' que evalúa 'falso'. –

Respuesta

12

En SpiderMonkey, las matrices se implementan básicamente como matrices C de jsvals. Estos se conocen como "matrices densas". Sin embargo, si comienzas a hacer cosas parecidas a un array, como tratarlas como objetos, su implementación cambiará a algo que se parece mucho a los objetos.

Moraleja de la historia: cuando desee una matriz, utilice una matriz. Cuando quieras un objeto, usa un objeto.

Oh, un jsval es un tipo de tipo variable que puede representar cualquier posible valor de JavaScript en un tipo C de 64 bits.

6

En V8 y Carakan (y presumiblemente Chakra), todos los objetos (no host) (tanto los que son matrices como los que no) con propiedades cuyos nombres son índices de matriz (como se define en ES5) se almacenan como ya sea una matriz densa (una matriz de C que contiene una envoltura de cierto valor) o una matriz dispersa (que se implementa como un árbol de búsqueda binario).

La representación del objeto unificado se muestra en que afecta el orden de enumeración: con un objeto, SpiderMonkey y SquirrelFish dan todas las propiedades en orden de inserción; y con una matriz, en general (¡hay casos especiales en SM al menos!), los índices de matriz primero, y luego todas las demás propiedades en orden de inserción. V8, Carakan y Chakra siempre dan índices de matriz primero y luego todas las demás propiedades en orden de inserción, independientemente del tipo de objeto.

Cuestiones relacionadas