Подтвердить что ты не робот

Eval - это зло, но разве оно испорчено?

Если я запустил это:

eval('{ear: {"<=": 6}}');

Я получаю сообщение об ошибке:

Uncaught SyntaxError: Неожиданный токен:

Создайте объект вручную:

var foo = {};
foo.ear = {};
foo.ear["<="] = 6;

Теперь, следующий код:

JSON.stringify(foo)

Возвращает следующую строку:

'{ "уха": { "< =": 6}}'

Та же строка, что и я, с которой я начал (за исключением белых символов, но это не имеет значения), поэтому eval(JSON.stringify(foo)) возвращает одно и то же сообщение об ошибке синтаксического сообщения. Однако:

$.parseJSON(JSON.stringify(foo))

выполняется правильно. В чем причина этого?

EDIT:

Как указывали nnnnnn и Рон Дадон, исходная строка и результат stringify различны. Однако, как я указал в вопросе, даже результат stringify, используемый в качестве ввода для eval, приведет к сообщению синтаксической ошибки.

EDIT2:

На основе ответов и экспериментов эта функция интересна:

function evalJSON(text) {
    return eval("(" + text + ")");
}
4b9b3361

Ответ 1

Основные {} анализируются как заявка блока.

попробуйте скопировать в скобки:

eval('({ear: {"<=": 6}})');

В javascript {} может быть проанализирован как блок или объект

примеры:

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

Ответ 2

Это не испорчено. Чтобы понять, что происходит, вам нужно понять, какие выражения видны (слева направо) парсером.

Простой способ войти в него - это играть с Javascript AST Visualizer


  • Вы получите то же самое исключение с гораздо более простым {"b":4}. Он анализировался как "b":4 внутри block. Это недействительный javascript. Нет дерева АСТ для вас... Однако из-за исключения внутри оператора {}. Это a BlockStatement. AST tree: Дерево AST для {}

  • Аналогичный {b:4} будет пониматься как b:4, действительный оператор js - a b label для 4... Это проанализировано как Дерево AST для {b: 4}

  • Наконец, a ({b:4}) будет пониматься как объявление объекта с свойством b, равным 4. Это проанализировано как Дерево AST для ({b: 4})


ECMAScript 2015

Вкл Блоки:

Блок: {StatementList}

В eval: Eval создает новый Realm, который анализируется (здесь несколько шагов) в виде последовательности Statement (a StatementList), которая, в свою очередь, this раздел имеет BlockStatement как первый вариант. Этот должен начинаться с { (см. Выше), поэтому, если вы оберните его скобкой (({})), то не может быть BlockStatement... Но если он соответствует BlockStatement, то должен быть BlockStatement.

Примечание в разделе Выражения:

ExpressionStatement не может начинаться с U + 007B (LEFT CURLY BRACKET), потому что это может сделать его неоднозначным с блоком

Ответ 3

Должны быть оценены литеральные обозначения объектов. Это происходит, когда вы назначаете переменную:

var a = {ear: {"<=": 6}};

или когда вы помещаете круглые скобки вокруг него, анонимный объект:

({ear: {"<=": 6}});

В противном случае фигурные скобки обрабатываются как маркеры блоков. В вашем случае это означает, что {ear:...} - это определение метки, метка называется ухом. Следующий блок {"<=": 6} дает вам синтаксическую ошибку, потому что "<=": 6 является недопустимым синтаксисом.

То же самое относится, если вы помещаете это в оператор eval.