2012-02-07 12 views
6

Stavo cercando di stringificare un oggetto tipo array che è stato dichiarato come oggetto array e ho trovato che JSON.stringify non stava elaborando correttamente un oggetto tipo array quando è definito come un oggetto array.Oggetto array JavaScript vs matrice come oggetti - Chiarimento

Vedi di seguito per maggiore chiarezza, ->jsFiddle

var simpleArray = []; //note that it is defined as Array Object 

alert(typeof simpleArray); // returns object -> Array Object 

simpleArray ['test1'] = 'test 1'; 
simpleArray ['test2'] = 'test 2'; 

alert(JSON.stringify(simpleArray)); //returns [] 

Ha funzionato bene e mi {"test1":"test 1","test2":"test 2"} restituito quando ho cambiato

var simpleArray = [];-var simpleArray = {};.

Qualcuno può far luce o qualche riferimento dove posso leggere di più?

Edit:

Domanda: Quando typeof simpleArray = [] e simpleArray = {} oggetto restituito, perché JSON.stringify non è stato in grado di tornare {"test1":"test 1","test2":"test 2"} in entrambi i casi?

risposta

2

Non si desidera un array. Quando vuoi un "array associativo" in JavaScript, vuoi veramente un oggetto, {}.

Si possono distinguere con instanceof Array:

[] instanceof Array // true 
({}) instanceof Array // false 

EDIT: può elaborarlo. Serializza tutti gli elementi dell'array. Tuttavia, per essere un elemento, ci deve essere un tasto numerico. In questo caso, non ce ne sono.

Questo non è niente di speciale per JSON. È coerente con toSource e la proprietà length.

+0

Capisco questa parte, quello che volevo sapere è il motivo per cui JSON.stringify non può essere elaborato se dichiarato come []. –

+0

Grazie! Stavo cercando l'istanza. Stavo cercando di usare typeof che restituiva oggetto in entrambi i casi. –

+1

Dato che ES 5 c'è anche 'Array.isArray (...)' (15.4.3.2) che al contrario è frame-safe. Può essere emulato. – PointedEars

4

La differenza è gli indici. Quando si utilizza un array [], gli indici possono essere solo interi positivi.

Così il seguente è sbagliato:

var array = [ ]; 
array['test1'] = 'test 1'; 
array['test2'] = 'test 2'; 

perché test1 e test2 non sono numeri interi. Al fine di risolvere il problema è necessario utilizzare gli indici basati su interi:

var array = [ ]; 
array[0] = 'test 1'; 
array[1] = 'test 2'; 

o se si dichiara un oggetto JavaScript quindi le proprietà possono essere tutte le stringhe:

var array = { }; 
array['test1'] = 'test 1'; 
array['test2'] = 'test 2'; 

che è equivalente a:

var array = { }; 
array.test1 = 'test 1'; 
array.test2 = 'test 2'; 
+0

Quindi cosa succede quando si esegue 'var simpleArray = []; simpleArray ['test2'] = 'test 2'; '? –

+3

@MattFenwick, quello che succede è che contrariamente a quanto ci si potrebbe aspettare: 'simpleArray.length = 0' che significa che non ci sono elementi in questo array. Puoi ancora usare 'simpleArray.test2' per accedere alla proprietà che hai definito. È solo un codice confuso che dovrebbe essere evitato. –

+0

+1 per la spiegazione dettagliata, ma quello che volevo sapere è il motivo per cui JSON.stringify non può essere elaborato se dichiarato come []. Ho provato a usare typeof e mi ha restituito oggetto in entrambi i casi. Ho intenzione di aggiungere questo alla mia domanda. –

1

Quando JSON.stringify incontra un array, iterate in un modo simile ad un anello for da 0 a simpleArray.length per trovare i valori. Ad esempio:

var a = []; 
a[5] = "abc"; 
alert(JSON.stringify(a)); // alerts [null,null,null,null,null,"abc"] 

Pertanto, le proprietà di impostazione su di esso saranno completamente invisibili a JSON.

Tuttavia, definendo l'oggetto con {}, JSON lo tratta come un oggetto e quindi esegue il ciclo sulle proprietà dell'oggetto (escluse le proprietà ereditate dalla catena del prototipo). In questo modo è possibile trovare le proprietà test1 e test2 e restituire correttamente ciò che si aspetta.

2

"Qualcuno può far luce o qualche riferimento dove posso leggere di più?"

Quando hai a che fare con i dati JSON, è possibile fare riferimento a json.org per leggere i requisiti del disciplinare.

In JSON, uno Array è un elenco di ordini di valori separati da ,.

enter image description here

Così il JSON.stringify() è semplicemente ignorando tutto ciò che non poteva essere rappresentato come un semplice elenco ordinato.

Quindi, se lo fai ...

var simpleArray = []; 
simpleArray.foo = 'bar'; 

... Sei ancora dare un array, quindi è in attesa solo indici numerici, e ignorando tutto il resto.

Poiché JSON è indipendente dalla lingua, i metodi per lavorare con JSON devono decidere quale struttura della lingua è più adatta per ciascuna struttura JSON.

Così JSON ha le seguenti strutture ...

{} // object 
[] // array 

Si dovrebbe notare che anche se l'aspetto molto simile a JavaScript oggetti e array, non sono rigorosamente la stessa.

Qualsiasi struttura JavaScript utilizzata per creare le strutture JSON deve essere conforme a quanto consentito dalle strutture JSON. Questo è il motivo per cui le proprietà non numeriche sono rimosse escluse.

Mentre JavaScript non si preoccupa di loro, JSON non li tollera.

+0

Le proprietà non numeriche (meglio: proprietà con nome * non numerico *) non vengono rimosse.Non sono considerati per l'iterazione in primo luogo. – PointedEars

+0

@PointedEars: era una formulazione scadente. Intendevo rimosso come una questione di prospettiva dello sviluppatore, come in * "Ehi, sono nel mio oggetto Array, ma non nel mio testo JSON!" *. Avrei dovuto dire * "escluso" *. –

-1

Il codice non è semanticamente corretto, ma poiché la maggior parte dei motori JavaScript sono davvero belli sul programmatore, consentono questi tipi di errori .

Un test rapido:

var a = []; 
a.b = "c"; 
console.log(JSON.stringify(a));//yields [], and not {"b":"c"} as you might expect 

Questo potrebbe essere causa di qualche severità in JSON.stringify che tratta ancora a come un Array. Non mi preoccuperei troppo di tanto. Questa è una situazione che non dovrebbe verificarsi nel tuo programma perché è un errore. JSLint è uno strumento popolare per catturare questi e molti altri potenziali problemi nel codice.

+0

Per favore, cosa c'è di sbagliato nella * sintassi *? – PointedEars

+0

Ho pensato che fosse piuttosto ovvio: non è possibile dichiarare chiavi di stringa in 'Array's. Solo perché la maggior parte dei motori JavaScript accetta non lo fa _correct_. Spero tu abbia pensato che il down-vote ne valesse la pena. – Halcyon

+0

Hai dei malintesi sulla natura di JavaScript, degli oggetti ECMAScript e di ciò che appartiene alla sintassi di un linguaggio di programmazione. Un commento è quello di abbreviarlo. * Non ci sono chiavi. * Gli oggetti hanno * proprietà * con nomi. I nomi di proprietà sono * stringhe *, accessibili con '[' ... ']', '.', o implicitamente (catena di portata). JavaScript è un'implementazione di ECMAScript. Di * JavaScript * ci sono solo due "implementazioni" di qualità di produzione: SpiderMonkey e Rhino; altri come JScript sono implementazioni * ECMAScript *. Continua ... – PointedEars

0

In Javascript, tutto è un oggetto, quindi anche array. Questo è il motivo per cui si ottiene:

>> var l = [1, 2]; 
>> typeof l 
"object" 

array vengono memorizzati nello stesso modo come oggetti. Quindi, in realtà, gli array sono solo oggetti hashtable. L'indice che fornisci quando accedi ad es.

>> l[0] 

non è interpretato come un offset, ma viene assegnata e quindi cercati.

Quindi gli array, sono solo oggetti (con alcuni metodi di array incorporati) e quindi è possibile trattarli come oggetti e inserire un valore sotto un determinato tasto. Ma solo le chiavi indicizzate dai numeri vengono utilizzate per calcolare la lunghezza.

>> var l = [] 
>> l.length 
0 
>> l[5] = 1; 
>> l.length 
6 
>> l 
[undefined, undefined, undefined, undefined, undefined, 1] 
>> l.hello = "Hello" 
>> l.length 
6 

Array - MDN Leggi per ulteriori informazioni e Associative Arrays considered harmful perché non si dovrebbe fare questo.

+0

Non * tutto * è un oggetto. Ci sono valori primitivi. Ma non c'è "Javascript", esistono diverse implementazioni ECMAScript. – PointedEars

1

Le differenze tra istanze Array e altri oggetti sono specificate in ECMAScript Language Specification, Edition 5.1, sezione 15.4.

Troverete lì che, mentre è possibile utilizzare la sintassi di proprietà di accesso staffa con tutti i riferimenti agli oggetti -

objRef[propertyName] 

- Array casi sono speciali. Solo utilizzando un valore di parametro la cui rappresentazione di stringa è quella di un valore intero a 32 bit senza segno inferiore a 2 -1 accede a un elemento della struttura di matrice incapsulata e l'accesso in scrittura influisce sul valore della proprietà dell'istanza Array.

La sezione 15.12 specifica l'oggetto JSON e il relativo metodo stringify di conseguenza.

Problemi correlati