Las técnicas "eval ()" y "JSON.parse ()" utilizan formatos mutuamente excluyentes.
- Con "eval ()" se requieren paréntesis .
- Con "JSON.parse ()" los paréntesis están prohibidos .
Tenga cuidado, hay funciones "stringify ()" que producen el formato "eval". Para ajax, debe usar solo el formato JSON.
Mientras que "eval" incorpora todo el lenguaje JavaScript, JSON usa solo un pequeño subconjunto del lenguaje. Entre las construcciones en el lenguaje JavaScript que "eval" debe reconocer está la "declaración de bloque" (también conocida como "declaración compuesta") ; que es un par o llaves "{}" con algunas declaraciones dentro. Pero las llaves también se utilizan en la sintaxis de los objetos literales. La interpretación se diferencia por el contexto en el que aparece el código. Algo puede parecerle un objeto literal, pero "eval" lo verá como una declaración compuesta.
En el lenguaje JavaScript, los objetos literales aparecen a la derecha de una asignación.
var myObj = { ...some..code..here... };
Los objetos literales no ocurren por sí solos.
{ ...some..code..here... }
Volviendo a la pregunta original del OP, formulada en 2008, preguntó por qué lo siguiente falla en "eval ()":
{ title: "One", key: "1" }
La respuesta es que parece una declaración compuesta. Para convertirlo en un objeto, debe ponerlo en un contexto donde una declaración compuesta es imposible. Eso se hace poniendo paréntesis alrededor.
( { title: "One", key: "1" } )
El PO también preguntó por qué una declaración similar hizo con éxito eval:
[ { title: "One", key: "1" }, { title: "Two", key: "2" } ]
Se aplica la misma respuesta: las llaves se encuentran en un contexto en el que una declaración compuesta es imposible. Este es un contexto de matriz, " [...]
" y las matrices pueden contener objetos, pero no pueden contener declaraciones.
A diferencia de "eval ()", JSON es muy limitado en sus capacidades. La limitación es intencionada. El diseñador de JSON pretendía un subconjunto minimalista de JavaScript, utilizando solo la sintaxis que podría aparecer en el lado derecho de una tarea. Entonces, si tiene algún código que se analiza correctamente en JSON ...
var myVar = JSON.parse("...some...code...here...");
... eso implica que también analizará legalmente en el lado derecho de una asignación, como esta ...
var myVar = ...some..code..here... ;
Pero esa no es la única restricción en JSON. La especificación del lenguaje BNF para JSON es muy simple. Por ejemplo, no permite el uso de comillas simples para indicar cadenas (como lo hacen JavaScript y Perl) y no tiene una forma de expresar un solo carácter como un byte (como lo hace 'C'). Desafortunadamente, tampoco permite comentarios (lo que sería muy bueno al crear archivos de configuración). La ventaja de todas esas limitaciones es que el análisis de JSON es rápido y no ofrece la oportunidad de inyectar código (una amenaza a la seguridad).
Debido a estas limitaciones, JSON no utiliza paréntesis. En consecuencia, un paréntesis en una cadena JSON es un carácter ilegal.
Utilice siempre el formato JSON con ajax, por las siguientes razones:
- Se configurará una canalización ajax típica para JSON.
- El uso de "eval ()" será criticado como un riesgo de seguridad.
Como ejemplo de una canalización ajax, considere un programa que involucra un servidor Node y un cliente jQuery. El programa cliente usa una llamada jQuery que tiene el formulario $.ajax({dataType:'json',...etc.});
. JQuery crea un objeto jqXHR para su uso posterior, luego empaqueta y envía la solicitud asociada. El servidor acepta la solicitud, la procesa y luego está listo para responder. El programa servidor llamará al método res.json(data)
para empaquetar y enviará la respuesta. De vuelta en el lado del cliente, jQuery acepta la respuesta, consulta el objeto jqXHR asociado y procesa los datos formateados JSON. Todo esto funciona sin necesidad de conversión manual de datos. La respuesta no implica una llamada explícita a JSON.stringify () en el servidor Node, ni una llamada explícita a JSON.parse () en el cliente; todo eso se maneja por ti.
El uso de "eval" está asociado con riesgos de seguridad de inyección de código. Puede pensar que eso no puede suceder de ninguna manera, pero los piratas informáticos pueden ser bastante creativos. Además, "eval" es problemático para la optimización de Javascript.
Si se encuentra usando una función "stringify ()", tenga en cuenta que algunas funciones con ese nombre crearán cadenas que son compatibles con "eval" y no con JSON. Por ejemplo, en Node, lo siguiente le brinda una función que crea cadenas en formato compatible con "eval":
var stringify = require('node-stringify');
Esto puede ser útil, pero a menos que tenga una necesidad específica, probablemente no sea lo que desea.