2012-02-10 16 views
18

La differenza tra uno javascript Array e Object non è molto grande. In realtà sembra Array aggiunge principalmente il campo length, in modo da poter utilizzare sia Array s e Object s come matrici numeriche:Gli array javascript sono effettivamente implementati come array?

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. 

Così le mie domande è, nei motori javascript popolari (V8, JavaScriptCore, SpiderMonkey, ecc.), come viene gestito? Ovviamente non vogliamo che i nostri array vengano effettivamente memorizzati come mappe di hash con valori chiave! Come possiamo essere ragionevolmente sicuri che i nostri dati siano archiviati come un vero array?

Per quanto posso vedere ci sono alcuni approcci motori potrebbe assumere:

  1. Array è implementato esattamente allo stesso modo di Object - come un array associativo con le chiavi di stringa.
  2. Array è un caso speciale, con una matrice -come std::vector sostenere i tasti numerici, e alcuni euristica densità per impedire l'uso della memoria folle se si fa ar[100000000] = 0;
  3. Array è lo stesso Object, e tutti gli oggetti ottenere un euristico per vedere se l'utilizzo di un array avrebbe più senso.
  4. Qualcosa follemente complicato a cui non ho pensato.

realtà questo sarebbe più semplice se ci fosse un tipo di matrice corretta (tosse WebGL array tipizzati tosse).

+2

Questo [articolo] (http://news.qooxdoo.org/javascript-array-performance-oddities-characteristics) è un po 'vecchio e non spiega esplicitamente l'implementazione. Tuttavia, esegue misurazioni dettagliate delle prestazioni e ne deduce le probabili implementazioni. –

+2

L'array non è _just_ una mappa con una proprietà 'length' attaccata. Se lo fosse, allora lo spostamento o il nonshifting interromperà l'indicizzazione (ad es.sposta un valore fuori da un array e inizia ancora dall'indice 0, non 1). Quindi c'è almeno un po 'di più in corso. (Non che questo dica necessariamente qualcosa sull'implementazione, ovviamente) – Flambino

+1

Perché dovresti aspettarti 'r [0] == ob [0] == ar [" 0 "] == ob [" 0 "] == ar. bar == ob.bar' per essere vero? ''a' == 'a' == 'a'' è falso perché valuta' true ==' a'' che valuta 'false'. –

risposta

12

In SpiderMonkey, gli array sono implementati fondamentalmente come array C di jsvals. Questi sono indicati come "array densi". Tuttavia, se inizi a fare cose un-array-like - come trattarli come oggetti - la loro implementazione è cambiata in qualcosa che assomiglia molto agli oggetti.

Morale della trama: quando si desidera un array, utilizzare un array. Quando vuoi un oggetto, usa un oggetto.

Oh, un jsval è una sorta di tipo variadic che può rappresentare qualsiasi possibile valore JavaScript in un tipo C a 64 bit.

6

In V8 e Carakan (e presumibilmente Chakra), tutti gli oggetti (non host) (sia quelli che sono matrici che quelli che non lo sono) con proprietà i cui nomi sono indici di array (come definito in ES5) vengono memorizzati come o un array denso (un array C contenente un value wrapper) o un array sparse (che è implementato come un albero di ricerca binario).

La rappresentazione di oggetto unificato mostra in che influisce sull'ordine di enumerazione: con un oggetto, SpiderMonkey e SquirrelFish forniscono entrambe le proprietà nell'ordine di inserimento; e con un array, in generale (ci sono casi speciali in SM almeno!) indici di array prima di tutte le altre proprietà nell'ordine di inserimento. V8, Carakan e Chakra forniscono sempre indici di array prima di tutte le altre proprietà nell'ordine di inserimento, indipendentemente dal tipo di oggetto.

Problemi correlati