Добавление строки в DOM преобразуется в JSON

#javascript #json #dom-manipulation

#javascript #json #dom-манипуляция

Вопрос:

Я пытаюсь написать быструю макетную функцию для модульного теста. Чтобы проверить мои утверждения, мне нужен HTML-элемент, который должен быть на странице, и этот элемент содержит stringified JSON. Тестируемая система принимает stringified JSON, изменяет его, преобразует обратно и повторно вставляет.

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

Вот пример кода

 var mockJson = JSON.stringify({
    name: "Foo",
    data: {}
});
var mockScript = document.createElement("script");
mockScript.id = "myElement";
mockScript.textContent = mockJson;
document.body.appendChild(mockScript);
  

Приведенный выше код на самом деле работает нормально. При запуске я вижу добавленное #myElement в DOM, и оно содержит мой строковый макет объекта.

Однако это также выдает ошибку:

VM136:1 Неперехваченная синтаксическая ошибка: неожиданный токен ‘:’

Похоже, что эта ошибка возникает специально в последней строке скрипта. Я был в замешательстве, потому : что ее нет в этой строке. Но я понял, что на самом деле он обрабатывает stringified mockJson как JSON… но в то же время работает нормально.

Я протестировал удаление сложного макетного объекта и замену его простой строкой:

 var mockJson = "foo";
var mockScript = document.createElement("script");
mockScript.id = "myElement";
mockScript.textContent = mockJson;
document.body.appendChild(mockScript);
  

При запуске этого скрипта он по-прежнему выполняет то, что должен, мой элемент script отображается в DOM со строкой «foo» внутри него. Но также появляется ошибка, которая в этом случае говорит:

VM179:1 Неперехваченная ошибка ссылки: foo не определен

Поэтому он пытается вставить foo как переменную, несмотря на то, что она объявлена как строка.

Почему это происходит? Почему он одновременно добавляет ее как строку, как и предполагалось, но также выдает эту ошибку?

Пример скрипки

     var mockJson = JSON.stringify({
        name: "Foo",
        data: {}
    });
    var mockScript = document.createElement("script");
    mockScript.id = "myElement";
    mockScript.textContent = mockJson;
    document.body.appendChild(mockScript);  

Комментарии:

1. «на самом деле он обрабатывает stringified mockJson как JSON …» — Нет, это не так. Он обрабатывает добавляемое <script>{ "name": "Foo", "data": {} }</script> как то, что оно есть: <scrip> тег с недопустимым синтаксисом

2. «… несмотря на то, что она объявлена как строка». — Вы используете строку, но она заканчивается как <script>foo</script> в DOM, что приведет к упомянутому ReferenceError

Ответ №1:

Это не имеет ничего общего с добавлением данных в DOM. Это именно то, что происходит, когда вы помещаете JSON в элемент script.

Ожидается, что элементы скрипта будут содержать JavaScript, а не JSON.

Строковый литерал является совершенно допустимым (хотя и совершенно бессмысленным) Выражение JavaScript.

 "A string"  

Литерал объекта не является.

 { "property": "value", "second property": "value" }  

Это связано с тем, что синтаксис {} используется как для объектных литералов, так и для блоков. В этом контексте он рассматривается как блок. Первым свойством является метка. Строка после нее — бессмысленная строка (как в предыдущем примере). Затем следующее : вызывает ошибку.

Если вы хотите добавить JSON на страницу для автоматического тестирования, используйте элемент, где это имеет некоторый смысл. Например <pre> , элемент вместо <script> элемента.

Несколько грязным взломом было бы установить type атрибут для элемента script, чтобы объявить, что это не JavaScript.

Комментарии:

1. Мне нужно, чтобы она была в теге script, поскольку это то, что имеет фактическая реализация.

2. Если то, что вы делаете, соответствует тому, что делает фактическая реализация, тогда фактическая реализация также выдаст эту ошибку.

3. Это не так. Я решил это, создав тип скрипта ld json таким, какой он есть. Это допустимые связанные данные.

4. Итак … то, что я сказал в последнем абзаце.

5. @Quentin Номер столбца, в котором была обнаружена ошибка, по-видимому, является артефактом того, как фрагменты стека составляются и выполняются нажатием кнопки. Автономное тестирование сообщает об ошибке, вызванной первым двоеточием, что согласуется с синтаксисом меток операторов, являющихся идентификатором, за которым следует двоеточие.