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

Почему JavaScript нуждается в скобках для оценки данных JSON?

Я узнал (трудный путь), что мне нужно добавить круглые скобки вокруг данных JSON, например:

stuff = eval('(' + data_from_the_wire + ')');
// where data_from_the_wire was, for example {"text": "hello"}

(В Firefox 3, по крайней мере).

В чем причина этого? Я ненавижу писать код, не понимая, что за капотом.

4b9b3361

Ответ 1

Помещение круглых скобок вокруг data_from_the_wire фактически эквивалентно

stuff = eval('return ' + data_from_the_wire + ';');

Если вы должны были вычислять без круглых скобок, тогда код будет оцениваться, и если бы у вас были какие-либо именованные функции внутри, они были бы определены, но не возвращены.

Возьмем в качестве примера возможность вызова функции так же, как она была создана:

(function() { alert('whoot'); })()

Вызов функции, которая только что была определена. Однако следующее не работает:

function() { alert('whoot'); }()

Итак, мы видим, что круглые скобки эффективно превращают код в выражение, которое возвращает, а не только код для запуска.

Ответ 2

eval принимает последовательность операторов Javascript. Парсер Javascript интерпретирует 'токен, происходящий внутри оператора как начало блока, а не начало литерала объекта.

Когда вы вставляете свой литерал в круглые скобки следующим образом: ({ data_from_the_wire }) вы переключите парсер Javascript в режим анализа выражений. Токен {внутри выражения означает начало объявления литерала объекта и не блока, и, следовательно, Javascript принимает его как литерал объекта.

Ответ 3

Я не уверен в причине, но я разбираю JSON, используя класс JSON из json.org. Это гораздо безопаснее, чем использование eval.

Ответ 4

В JavaScript фигурные скобки используются для создания операторов блока:

{
var foo = "bar";
var blah = "baz";
doSomething();
}

Вышеуказанные строки могут быть помещены внутри строки и eval без проблем. Теперь рассмотрим следующее:

{
"foo": "bar",
"blah": "baz"
}

Кудрявые скобки заставляют механизм JavaScript думать, что это групповое выражение, поэтому синтаксическая ошибка вокруг символа :. Цитата из MDN... Руководство JavaScript... Литералы объектов:

Вы не должны использовать литерал объекта в начале инструкции. Это приведет к ошибке или не будет вести себя так, как вы ожидаете, потому что { будет интерпретироваться как начало блока.

Обходной способ обертывания литерала объекта внутри () работает, сообщая движку обрабатывать его содержимое как выражение, а не как оператор блока. Так что это не работает:

({
var foo = "bar";
var blah = "baz";
doSomething(evil);
})
// parse error

Но это делает:

({
"foo": "bar",
"blah": "baz"
})
// returns object

Ответ 5

Это происходит потому, что без округлых скобок JavaScript пытается интерпретировать {"text": ... как метку и терпит неудачу. Попробуйте в консоли, и вы получите ошибку "неправильной метки".

Ответ 6

В действительности это зависит от значения data_from_the_wire. В большинстве случаев ваш синтаксис в порядке, но строка, начинающаяся с {, анализируется как метка, а ваша неверна. Если вы окружаете его круглыми скобками, это предотвращает неправильный интерпретатор вашего анализа.

Просто проблема синтаксического анализа. С строками, числами или функциями у вас не будет этой проблемы.

Одно из решений - всегда давать инструкции, а не выражения. Вы можете написать

eval('var stuff = {"text": "hello"}');

Ответ 7

Я не знаю, и меня действительно интересует ответ на этот вопрос, но я предполагаю, что без круглых скобок данные в data_from_the_wire будут интерпретироваться как замыкание. Возможно, скобки принудительно оценивают и поэтому ассоциативный массив "возвращается".

Это вид угадывания, который приводит к downvotes, хотя =).

ИЗМЕНИТЬ

Дуглас Крокфорд упоминает двусмысленность синтаксиса на своем JSON, но это мне действительно не помогло.