javascript - online - eval es malvado, pero es defectuoso?
javascript>: eval (3)
Esta pregunta ya tiene una respuesta aquí:
Si ejecuto esto:
eval(''{ear: {"<=": 6}}'');
Me sale un error:
SyntaxError no detectada: fichas inesperado :
Vamos a crear el objeto manualmente:
var foo = {};
foo.ear = {};
foo.ear["<="] = 6;
Ahora, el siguiente código:
JSON.stringify(foo)
Devuelve la siguiente cadena:
''{"oreja": {"<=": 6}}''
La misma cadena con la que empecé (excepto los caracteres blancos, pero son irrelevantes), por lo que eval(JSON.stringify(foo))
devuelve el mismo mensaje de error de sintaxis. Sin embargo:
$.parseJSON(JSON.stringify(foo))
Se ejecuta correctamente. ¿Cuál es la razón de eso?
EDITAR:
Como nnnnnn y Ron Dadon señalaron, la cadena inicial y el resultado de la stringify
son diferentes. Sin embargo, como señalé en la pregunta, incluso el resultado de la stringify
de la stringify
de stringify
como entrada para eval
generará un mensaje de error de sintaxis.
EDIT2:
Basada en las respuestas y experimentos realizados, esta función es interesante:
function evalJSON(text) {
return eval("(" + text + ")");
}
Las notaciones literales de objetos necesitan ser evaluadas. Esto sucede cuando asignas una variable:
var a = {ear: {"<=": 6}};
o cuando pones paréntesis a su alrededor, un objeto anónimo:
({ear: {"<=": 6}});
De lo contrario, los paréntesis se analizan como marcadores de bloque. En su caso, esto significa que {ear:...}
es una definición de etiqueta, la etiqueta se llama ear. El siguiente bloque {"<=": 6}
le da un error de sintaxis porque "<=": 6
no es una sintaxis válida.
Lo mismo se aplica si pones esto en una declaración eval
.
Las principales {}
se analizan como una instrucción de bloque .
tratar de envolver entre paréntesis:
eval(''({ear: {"<=": 6}})'');
En javascript {}
se puede analizar como un bloque o un objeto
ejemplos:
//object
var user = {
name: "John",
age: "32"
};
//block
{
let a = 5;
console.log(a);
}
//object:
var a = {};
console.log({});
return {};
({});
//block:
function(){}
for(k in o){}
{}
No tiene defectos. Para comprender lo que está sucediendo, debe comprender qué tipo de declaraciones ve (de izquierda a derecha) el analizador.
Una forma sencilla de acceder a él es jugar con un Visualizador AST de Javascript.
Obtendrá la misma excepción con mucho más simple
{"b":4}
. Se analiza como"b":4
dentro de un bloque . Eso no es válido javascript. No hay un árbol AST para usted ... Sin embargo, se debe a una excepción dentro de una declaración{}
. Eso es unBlockStatement
. Árbol de AST:Una
{b:4}
similar se entendería comob:4
, una declaración js válida - una labelb
para4
... Eso se analiza comoFinalmente, a
({b:4})
se entendería como una declaración de objeto con una propiedadb
igual a4
. Que se analiza como
ECMAScript 2015
En Blocks :
Bloque: {StatementList}
En eval mismo: Eval crea un nuevo Realm
, que se analiza (varios pasos aquí) como una secuencia de Statement
s (una StatementList
), que a su vez esta sección tiene BlockStatement
como primera opción. Esto debe comenzar con {
(ver arriba), así que si lo envuelve con un corchete ( ({})
) no puede ser un BlockStatement
... Pero si coincide como BlockStatement
, debe ser un BlockStatement
.
Una nota al margen en la sección de Expressions :
Un ExpressionStatement no puede comenzar con un U + 007B (BRACKET PENDIENTE IZQUIERDO) porque eso podría hacerlo ambiguo con un Bloque