首页 > 解决方案 > 将字符串附加到 DOM 会转换为 JSON

问题描述

我正在尝试为单元测试编写一个快速模拟函数。为了测试我的断言,我需要在页面中添加一个 HTML 元素,并且该元素包含字符串化的 JSON。被测系统采用字符串化的 JSON,对其进行修改,将其转换回来并重新插入。

在将我的模拟插入创建到 DOM 时,我注意到一个奇怪的地方,我的字符串化 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 未捕获的 SyntaxError:意外的令牌“:”

此错误似乎专门在脚本的最后一行运行。我很困惑,因为:不在那条线上。但我意识到它实际上将字符串化处理mockJson为 JSON ......但同时也运行良好。

我测试了删除复杂的模拟对象并用一个简单的字符串替换它:

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

运行此脚本时,它仍会执行应有的操作,我的脚本元素显示在 DOM 中,其中包含字符串“foo”。但也出现了一个错误,在这种情况下说:

VM179:1 未捕获的 ReferenceError:未定义 foo

所以它试图foo作为一个变量插入,尽管它被声明为一个字符串。

为什么会这样?为什么它既按预期同时将其添加为字符串,又抛出此错误?

小提琴示例

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

标签: javascriptjsondom-manipulation

解决方案


这与将数据附加到 DOM 无关。这就是将 JSON 放入脚本元素时发生的情况。

脚本元素应包含JavaScript,而不是 JSON。

字符串文字是一个完全有效(尽管完全没有意义)的 JavaScript 表达式。

"A string"

对象文字不是。

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

这是因为该语法{}同时用于对象字面量和块。在这种情况下,它被视为一个。第一个属性是标签。它后面的字符串是一个无意义的字符串(如前面的示例中所示)。然后下一个:触发错误。

如果您想将 JSON 添加到页面以进行自动化测试,请在有意义的地方使用元素。例如一个<pre>元素而不是一个<script>元素。

一个有点肮脏的技巧是type在脚本元素上设置一个属性来声明它不是 JavaScript。


推荐阅读