【问题标题】:why "</script>" in script tag treat as closing tag but "<h1> hlo </h1>" not render anything?为什么脚本标签中的“</script>”被视为结束标签,但“<h1> hlo </h1>”不渲染任何东西?
【发布时间】:2016-01-12 04:46:01
【问题描述】:

我在读一本书,然后我读到了这一行:- “HTML 解析器不知道您的 JavaScript 代码;它像对待任何其他文本一样对待它”。所以如果我们写:

<script type="text/javascript">
      alert("first");
      var string = "</script>";
</script>

我们收到一个错误,因为"&lt;/script&gt;" 作为 HTML 解析器的结束标记,第二行 &lt;/script&gt; 作为脚本的关闭,然后执行该脚本标记,并给出:-

Uncaught SyntaxError: Unexpected token ILLEGAL

即使第一个alert() 没有被执行?我不知道为什么?但我的主要问题是,如果"&lt;/script&gt;" 被视为标签,那么当我们写这样的东西时:

var str = "<h1> hello world </h1>"; 

那么这不会在屏幕上呈现任何“hello world”吗?根据前面的示例,HTML 解析器也应该将该字符串视为 HTML 标记,但事实并非如此?谁能给我解释一下?抱歉英语不好:(

【问题讨论】:

  • 因为它在脚本标签内,并且根据定义脚本标签被视为“显示:无”。
  • @Tiger:不止于此。脚本标签的内部内容被视为 CDATA - 也就是说,它们是文字文本字符串。但是在您的第一个示例中,脚本标记以第一个 &lt;/script&gt; 结尾,因此脚本以未关闭的 " 结尾,这是一个编译错误。
  • 解析工作如下:如果你看到&lt;script&gt;标签,逐字节扫描文本直到结束&lt;/script&gt;标签。然后获取该文本并将其传递给 javascript 解释器。由于 DOM 解析器只知道标签而不是 javascript 语法,因此标签在字符串声明内关闭。
  • simplay 将 var string = "&lt;/script&gt;"; 替换为 var string = "&lt;/sc" + "ript&gt;";

标签: javascript html


【解决方案1】:

您应该了解浏览器的工作原理。 HTML 和 Javascript 是如何呈现的。这是一个很好的阅读How browsers work

下面的文字来自上面的链接。

标记化算法

算法的输出是一个 HTML 标记。该算法表示为状态机。每个状态消耗输入流的一个或多个字符,并根据这些字符更新下一个状态。该决定受当前标记化状态和树构造状态的影响。这意味着相同的消费字符将根据当前状态为正确的下一个状态产生不同的结果。算法太复杂,带不完,看一个简单的例子,帮助我们理解原理。

基本示例 - 标记以下 HTML:

<html>
    <body>
        Hello world
    </body>
</html>

初始状态是“数据状态”。当遇到“" 字符被消耗掉。每个字符都附加到新的令牌名称。在我们的例子中,创建的令牌是一个“html”令牌。 当到达“>”标签时,当前令牌被发出,状态变回“数据状态”。 "" 标记将按相同的步骤处理。到目前为止,发出了“html”和“body”标签。我们现在回到“数据状态”。使用 "Hello world" 的 "H" 字符将导致创建和发出字符令牌,直到达到 "" 的 "”。然后新的标签令牌将被发出,我们回到“数据状态”。 "" 输入将像前一种情况一样处理。

&lt;/script&gt; 标签也是如此。这就是它的工作原理。

【讨论】:

  • 感谢这个有用的链接,但这现在回答了我认为的问题,根据您在浏览器读取时的回答

    它的状态应该改变并且它应该重新读取那个元素?但它不会这样做

【解决方案2】:

我想我得到了答案, 根据https://www.w3.org/TR/html4/types.html#type-cdata

虽然 STYLE 和 SCRIPT 元素使用 CDATA 作为其数据模型, 对于这些元素,用户代理必须以不同方式处理 CDATA。 标记和实体必须被视为原始文本并传递给 按原样应用。字符序列“

样式和脚本元素的文本使用 CDATA 作为其数据模型,并且该文本直接传递给应用程序(js 中的 javascript 解释器和 css(?) 中的布局引擎)和

字符序列“”的第一次出现被视为终止元素的结尾(在和/之间没有空格它在答案中不起作用,正常吗?)

所以当我写的时候:-

var string = "</script>";

组合“”被视为结束,文本内容(var string =“)被传递给js解释器,我们知道字符串没有正确结束(”缺失),所以显示错误,然后“ ); 像文本一样处理,为了解决这个问题,正如规范所说的 word 作为终止符的组合,我们可以这样写:-

var string = "<\/script>";

这里的 html 解析器不理解 javascript 代码,所以转义序列不起作用,对于 html 解析器这些都是 3 个单独的字符,还有其他很多变体可以打破“

例如:-

var str = "< /script>"; 

(您是否注意到 和 / 之间的空格,我不知道它是否是标准允许的,但它有效)

var str = "";

但还有一件事要记住:-

var str = "" + "pt>" 也可以。 (忘了空格,留个空格。)

因为根据:-

https://stackoverflow.com/a/236106/3810909

实际上,浏览器只在解析 CDATA 脚本块时结束 实际关闭标签。

谢谢,抱歉英语不好

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-05-17
    • 1970-01-01
    • 2022-01-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-12-31
    相关资源
    最近更新 更多