为什么通过 DOMParser 创建的脚本元素不执行

Why script elements created through DOMParser do not execute?

本文关键字:脚本 元素 执行 创建 DOMParser 为什么      更新时间:2023-09-26

我正在Ajax中加载HTML,用DOMParser解析它,并将文档正文的所有childNodes放入文档片段中。

当我将片段添加到当前文档的正文中时,不会执行<script>标签。

我摆弄了一下,发现如果我用新的动态创建的脚本标签替换它们,它们就会被正确执行。

我想知道为什么?

例如

var html = "Some html with a script <script>alert('test');</script>";
var frag = parsePartialHtml(html);

fixScriptsSoTheyAreExecuted(frag);

document.body.appendChild(frag);

function fixScriptsSoTheyAreExecuted(el) {
  var scripts = el.querySelectorAll('script'),
      script, fixedScript, i, len;
  for (i = 0, len = scripts.length; i < len; i++) {
    script = scripts[i];
    fixedScript = document.createElement('script');
    fixedScript.type = script.type;
    if (script.innerHTML) fixedScript.innerHTML = script.innerHTML;
    else fixedScript.src = script.src;
    fixedScript.async = false;
    script.parentNode.replaceChild(fixedScript, script);
  }
}

function parsePartialHtml(html) {
  var doc = new DOMParser().parseFromString(html, 'text/html'),
      frag = document.createDocumentFragment(),
      childNodes = doc.body.childNodes;
  while (childNodes.length) frag.appendChild(childNodes[0]);
  return frag;
}

如果不调用fixScriptsSoTheyAreExecuted,则不会执行任何内容。

我觉得很难遵循的另一点是,如果我尝试简单地克隆现有的脚本节点以使用 cloneNode 创建新节点,它不起作用,这表明最初由DOMParser创建的脚本标签带有阻止它们被执行的状态。

在 DOM 解析和序列化规范中有解释:

parseFromString

parseFromString(str, type)方法必须运行以下步骤, 取决于类型:

  • "text/html"

    使用 HTML parser 解析str,并返回新创建的文档。

    脚本标志必须设置为"禁用"。

    注意
    script元素被标记为不可执行,并且 noscript被解析为标记。