2010-09-29 15 views
5

Perché il seguente codice deve aggiungere ( e ) per eval?Perché dobbiamo aggiungere parentesi per eval JSON?

var strJson = eval("(" + $("#status").val().replace(";","") + ")"); 

PS: $("#status").val() sta tornando qualcosa di simile {"10000048":"1","25000175":"2","25000268":"3"};

+0

Perché stai utilizzando 'eval' in primo luogo? Basta scrivere con: 'var strJson = $ (" # status "). Val(). Replace ("; "," ");' –

risposta

3

eval prende una dichiarazione o un'espressione JavaScript, ma {...} sarebbe valida come una dichiarazione o un'espressione e la grammatica di JavaScript preferisce un'istruzione.

Come espressione:

{"10000048":"1","25000175":"2","25000268":"3"} 

è un oggetto con alcune proprietà (quello che volete).

Come un comunicato, si tratta di un blocco:

{      // begin Block 
    "10000048":   // LabelledStatement (but the quotes are invalid) 
     "1",   // Expression, calculate string "1" then discard it, then 
      "25000175": // you can't put a label inside an expression 

che dà un errore.

(etichette JavaScript può essere utilizzato per etichettare una dichiarazione particolare per l'uso con break/continue. Sono un po 'inutile e quasi mai utilizzato.)

Così aggiungendo le parentesi a risolvere l'ambiguità. Solo un'espressione può iniziare con (, quindi i contenuti vengono analizzati in un contesto di espressione, fornendo un oggetto letterale, non un contesto di istruzione.

Incidentalmente questo non è abbastanza abbastanza per interpretare correttamente tutti i possibili valori JSON. A causa di una svista nel design di JSON, i caratteri U + 2028 e U + 2029, due oscuri caratteri di fine riga Unicode, sono validi per mettere senza caratteri in una stringa JSON letterale, ma non in una stringa letterale JavaScript.Se vuoi essere sicuro, puoi evadere, ad esempio:

function parseJSON(s) { 
    if ('JSON' in window) return JSON.parse(s); 
    return eval('('+s.replace(/\u2028/g, '\\u2028').replace(/\u2029/g, '\\u2029')+')'); 
} 
4

Dipende da quello che il valore di tale elemento è (uno sconosciuto), avvolgendolo in () è la via sicura per tenere conto, eventualmente, di non ingresso essendo lì.

Edit: Ora che hai chiarito che di JSON, questo non è valido:

eval('{"10000048":"1","25000175":"2","25000268":"3"}'); 

Ma questo si tradurrà in un oggetto valido di essere restituito:

eval('({"10000048":"1","25000175":"2","25000268":"3"})'); 
//effectively: 
eval('return {"10000048":"1","25000175":"2","25000268":"3"};'); 

Picture in a JavaScript:

<script type="text/javascript"> 
    {"10000048":"1","25000175":"2","25000268":"3"} 
</script> 

Questo fallirà, è solo un oggetto dichiarato in linea ma non la sintassi corretta ... il Lo stesso motivo per cui un server ha per supportare JSONP perché funzioni.


Un po 'tangente alla domanda, ma dal momento che stai tra cui jQuery, si potrebbe anche usare $.parseJSON() (che utilizzerà il nativo JSON.parse() se disponibile) per questo:

var strJson = $.parseJSON($("#status").val().replace(";","")); 
+0

Salve il val() restituito è qualcosa come {"10000048": "1 ", "25000175": "2", "25.000.268": "3"}; – Ricky

+0

perché la prima affermazione non è valida – Ricky

+0

@Ricky - Non è una sintassi valida per lo stesso motivo per cui non è direttamente nello script, dal momento che il parser non la considera come un'espressione mentre l'aggiunta di '()' è effettivamente un'istruzione return (dal momento che passa a un'espressione, riconoscendo '{' come un oggetto che inizia, ottenendo/restituendo l'oggetto che ti interessa). –

Problemi correlati