Почему JavaScript нуждается в скобках для оценки данных JSON?
Я узнал (трудный путь), что мне нужно добавить круглые скобки вокруг данных JSON, например:
stuff = eval('(' + data_from_the_wire + ')');
// where data_from_the_wire was, for example {"text": "hello"}
(В Firefox 3, по крайней мере).
В чем причина этого? Я ненавижу писать код, не понимая, что за капотом.
Ответы
Ответ 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, но это мне действительно не помогло.