Le tecniche "eval ()" e "JSON.parse ()" utilizzano formati che si escludono a vicenda.
- Con "eval ()" le parentesi sono obbligatorie .
- Con "JSON.parse ()" le parentesi sono vietate .
Attenzione, ci sono funzioni "stringify ()" che producono il formato "eval". Per ajax, dovresti usare solo il formato JSON.
Sebbene "eval" incorpori l'intero linguaggio JavaScript, JSON utilizza solo un piccolo sottoinsieme del linguaggio. Tra i costrutti nel linguaggio JavaScript che "eval" deve riconoscere è l ' "istruzione Block" ( nota anche come "istruzione composta") ; che è una coppia o parentesi graffe "{}" con alcune istruzioni all'interno. Ma le parentesi graffe vengono utilizzate anche nella sintassi dei letterali oggetto. L'interpretazione è differenziata dal contesto in cui compare il codice. Qualcosa potrebbe sembrarti un oggetto letterale, ma "eval" lo vedrà come un'istruzione composta.
Nel linguaggio JavaScript, i valori letterali degli oggetti si trovano a destra di un compito.
var myObj = { ...some..code..here... };
I letterali oggetto non si verificano da soli.
{ ...some..code..here... } // this looks like a compound statement
Tornando alla domanda originale dell'OP, posta nel 2008, ha chiesto perché quanto segue fallisce in "eval ()":
{ title: "One", key: "1" }
La risposta è che sembra un'affermazione composta. Per convertirlo in un oggetto, è necessario inserirlo in un contesto in cui un'istruzione composta è impossibile. Ciò viene fatto inserendovi una parentesi
( { title: "One", key: "1" } ) // not a compound statment, so must be object literal
L'OP ha anche chiesto perché un'affermazione simile abbia avuto successo:
[ { title: "One", key: "1" }, { title: "Two", key: "2" } ]
La stessa risposta si applica: le parentesi graffe sono in un contesto in cui un'istruzione composta è impossibile. Questo è un contesto di array, " [...]
" e gli array possono contenere oggetti, ma non possono contenere istruzioni.
A differenza di "eval ()", JSON è molto limitato nelle sue capacità. La limitazione è intenzionale. Il progettista di JSON intendeva un sottoinsieme minimalista di JavaScript, utilizzando solo la sintassi che potrebbe apparire sul lato destro di un compito. Quindi, se hai del codice che analizza correttamente in JSON ...
var myVar = JSON.parse("...some...code...here...");
... ciò implica che analizzerà legalmente anche sul lato destro di un compito, come questo ..
var myVar = ...some..code..here... ;
Ma questa non è l'unica restrizione su JSON. La specifica del linguaggio BNF per JSON è molto semplice. Ad esempio, non consente l'uso di virgolette singole per indicare stringhe (come fanno JavaScript e Perl) e non ha un modo per esprimere un singolo carattere come byte (come fa 'C'). Sfortunatamente, inoltre, non consente commenti (il che sarebbe davvero bello quando si creano file di configurazione). Il vantaggio di tutte queste limitazioni è che l'analisi di JSON è veloce e non offre alcuna possibilità di iniezione di codice (una minaccia per la sicurezza).
A causa di queste limitazioni, JSON non può utilizzare le parentesi. Di conseguenza, una parentesi in una stringa JSON è un carattere illegale.
Usa sempre il formato JSON con ajax, per i seguenti motivi:
- Una tipica pipeline ajax verrà configurata per JSON.
- L'uso di "eval ()" sarà criticato come un rischio per la sicurezza.
Come esempio di una pipeline ajax, considera un programma che coinvolge un server Node e un client jQuery. Il programma client utilizza una chiamata jQuery avente il modulo $.ajax({dataType:'json',...etc.});
. JQuery crea un oggetto jqXHR per un uso successivo, quindi crea un pacchetto e invia la richiesta associata. Il server accetta la richiesta, la elabora e quindi è pronto a rispondere. Il programma server chiamerà il metodo res.json(data)
per creare il pacchetto e inviare la risposta. Tornando al lato client, jQuery accetta la risposta, consulta l'oggetto jqXHR associato ed elabora i dati formattati JSON. Tutto questo funziona senza alcuna necessità di conversione manuale dei dati. La risposta non implica alcuna chiamata esplicita a JSON.stringify () sul server Node e nessuna chiamata esplicita a JSON.parse () sul client; è tutto gestito per te.
L'utilizzo di "eval" è associato ai rischi per la sicurezza dell'iniezione di codice. Potresti pensare che non sia possibile, ma gli hacker possono diventare piuttosto creativi. Inoltre, "eval" è problematico per l'ottimizzazione Javascript.
Se ti ritrovi a utilizzare una funzione "stringify ()", tieni presente che alcune funzioni con quel nome creeranno stringhe compatibili con "eval" e non con JSON. Ad esempio, in Node, quanto segue fornisce una funzione che crea stringhe in formato compatibile "eval":
var stringify = require('node-stringify'); // generates eval() format
Questo può essere utile, ma a meno che tu non abbia un'esigenza specifica, probabilmente non è quello che vuoi.