2010-09-29 17 views
5

¿Por qué el siguiente código necesita agregar ( y ) para eval?¿Por qué necesitamos agregar paréntesis para evaluar JSON?

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

PS: $("#status").val() está volviendo algo así como {"10000048":"1","25000175":"2","25000268":"3"};

+0

¿Por qué está utilizando 'eval' en primer lugar? Simplemente quédese con: 'var strJson = $ (" # estado "). Val(). Replace ("; "," ");' –

Respuesta

3

eval toma una declaración o expresión de JavaScript, pero {...} sería válida como una declaración o una expresión, y la gramática de JavaScript prefiere una declaración.

Como expresión:

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

es un objeto con algunas propiedades (lo que quiere).

Como una declaración, que es un bloque:

{      // 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 

que da un error.

(etiquetas de JavaScript se pueden utilizar para etiquetar una declaración particular para su uso con break/continue. Son un poco inútil y casi nunca se utiliza.)

Así que mediante la adición de los paréntesis a resolver la ambigüedad. Solo una expresión puede comenzar con (, por lo que los contenidos se analizan en un contexto de expresión, dando un objeto literal, no un contexto de declaración.

Por cierto, esto no es bastante suficiente para interpretar correctamente todos los valores JSON posibles. Debido a un descuido en el diseño de JSON, los caracteres U + 2028 y U + 2029, dos caracteres oscuros que terminan de línea Unicode, son válidos para colocarlos en un literal de cadena JSON, pero no en un literal de cadena de JavaScript.Si desea estar seguro, puede escapar de ellos, por ejemplo:

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

Depende de lo que el valor de ese elemento es (un desconocido), envolviéndolo en () es la ruta segura para tener en cuenta, posiblemente, de sin de entrada estando allí.

Editar: Ahora que ha aclarado que de JSON, esto no es válido:

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

Pero esto se traducirá en un objeto válido de ser devuelto:

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

imagen en una JavaScript archivo:

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

Esto va a fracasar, es sólo un objeto declarado en línea, pero no la sintaxis correcta ... La misma razón por la que un servidor tiene para admitir JSONP para que funcione.


Un poco tangencial a la pregunta, pero ya que estás incluyendo jQuery, que también podría utilizar $.parseJSON() (que utilizará el nativo JSON.parse() si está disponible) para esto:

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

Hola el val() devuelto es algo así como {"10000048": "1 "," 25000175 ":" 2 "," 25000268 ":" 3 "}; – Ricky

+0

por qué la primera afirmación no es válida – Ricky

+0

@Ricky: simplemente no es una sintaxis válida por la misma razón que no está directamente en la secuencia de comandos, ya que el analizador no la ve como una expresión, mientras que agregar '()' es una declaración de retorno (ya que cambia a una expresión, reconociendo '{' como un inicio de objeto, obteniendo/devolviendo el objeto que le importa). –

Cuestiones relacionadas