2014-12-19 21 views
9

Ho avuto un po 'di risveglio sulla natura degli indici di array JavaScript di recente. Praticando, ho trovato il seguente (sto lavorando con Node.js in modalità interpretativa qui):Matrici JavaScript: stringhe indicizzate

var x=[]; 
x['a']='a'; 
console.log(x); // Yields [ a: 'a' ] 
console.log(x.length); // yields 0 not 1 
x[1]=1; 
console.log(x); // Yields [ , 1, a: 'a' ] 
console.log(x.length); // Yields 2 not 3 (one for empty 0 space, one for the occupied 1 space) 

È a: 'a' davvero quello che sembra - una proprietà oggetto incorporato in una matrice - e, quindi, non è contato nella proprietà dell'array .length?

+0

Neato. Non sapevo nemmeno che fosse possibile. Ha senso però come un array è solo un oggetto. – iambriansreed

risposta

13

In JavaScript, gli array sono solo oggetti con alcune proprietà speciali, come un length proprietà automatico, e alcuni metodi collegate (sort, pop, join, ecc). Infatti, a non verrà conteggiato nell'array, poiché la proprietà length di un array memorizza solo la quantità di elementi con un nome di proprietà che può essere rappresentato con un numero intero positivo a 32 bit.

E poiché le matrici sempre definiscono automaticamente ogni elemento numerato fino al massimo elemento con un positivo 32 bit nome proprietà int, ciò significa efficacemente i negozi di proprietà length1 superiore l'elemento con il massimo intero a 32 bit come nome immobile. Grazie @Felix Kling per avermi corretto su questo nei commenti.

L'aggiunta di proprietà come a non è vietata affatto, ma è necessario fare attenzione con loro, poiché potrebbe essere fonte di confusione durante la lettura del codice.

C'è anche una differenza di camminare attraverso gli elementi dell'array:

camminare attraverso tutti gli elementi numerati:

for (var i=0; i<myArray.length; i++) { 
    //do something 
} 

di camminare attraverso ogni proprietà che non è built-in:

for (var i in myArray) { 
    //do something 
} 

Si noti che questo ciclo includerà anche tutto ciò che è incluso da Array.prototype che non è un metodo integrato. Quindi, se dovessi aggiungere Array.prototype.sum = function() {/*...*/};, verrà eseguito anche il loop.

per verificare se l'oggetto che si sta utilizzando è effettivamente una matrice, e non solo un oggetto, è possibile eseguire il seguente test:

if (Object.prototype.toString.call(myObject) === '[object Array]') { 
    //myObject is an array 
} else if (typeof myObject === 'object') { 
    //myObject is some other kind of object 
} 

Vedi @artem's comment: myObject instanceof Array potrebbe non funzionare sempre in modo corretto.

+3

* "conta solo i valori numerabili nella matrice" * Sembra che considererebbe gli elementi della matrice stessa. 'Length' è sempre 1 + il nome di proprietà" maximum "che può essere convertito in un intero a 32 bit. –

+0

@FelixKling ringrazia per quella correzione. L'ho modificato di conseguenza nel mio post. – Joeytje50

+1

'myObject instanceof Array' potrebbe restituire false per alcuni array (non sono sicuro di node.js, ricordo un caso in cui array è stato passato da un altro iframe, apparentemente in alcuni browser ogni finestra ha la sua istanza di costruttore Array). È sempre una buona idea fare ciò che fa jQuery, in questo caso: 'Object.prototype.toString.call (myObject) === '[oggetto Array]'' – artem

2

Sì, è corretto. Ciò funziona perché praticamente tutto in JavaScript è un oggetto, inclusi array e funzioni, il che significa che è possibile aggiungere le proprie proprietà di stringa arbitrarie. Non è che tu dici che tu dovresti farlo.

Gli array ([]) devono essere indicizzati utilizzando numeri interi non negativi. Gli oggetti ({}) devono essere "indicizzati" utilizzando le stringhe.

+0

* Praticamente tutto in JavaScript è un oggetto *. Immagino tu intenda "tutti i valori in JavaScript sono oggetti, eccetto quelli primitivi, che includono numeri, stringhe, null e indefiniti". E perché non dovresti mettere le proprietà delle stringhe sugli array? È una tecnica perfettamente valida a seconda della situazione. –

3

Questo è corretto, ed è una buona illustrazione del fatto che il nuovo array che hai creato è in realtà solo un tipo speciale di oggetto. Infatti, typeof [] è 'object'!L'impostazione di una proprietà denominata su di essa (che potrebbe essere scritta in modo più pulito come x.a = 'a') è in realtà l'impostazione di una nuova proprietà per il wrapper degli oggetti attorno alla matrice "reale" (proprietà numerate, in realtà). Non influenzano la proprietà length per lo stesso motivo per cui il metodo Array.isArray non lo fa.

+0

Non esiste alcun "object wrapper" attorno alla matrice. L'array ** è ** l'oggetto. –

+0

Sì, è tecnicamente vero. Ma se stai usando un array è perché vuoi specificamente il pezzo di lista ordinato, e quindi ha senso pensarlo come diverso (e con usi diversi) rispetto a "Oggetto". Anche il tipo 'Number' è tecnicamente un oggetto (che è ereditato da' Object.prototype'), ma è davvero inutile pensarlo come uno. Il mio termine "object wrapper" è solo un'astrazione per distinguere una matrice da un oggetto semplice. – OverlappingElvis

Problemi correlati