我正在阅读this问题,接受的答案是:
通过设置元素的innerHTML属性添加的脚本不会被执行。
但是当我尝试更改以下代码中第一个<script>
标记的innerHTML时:
<script></script>
<script>
document.querySelectorAll("script")[0].innerHTML = 'console.log("Test")';
</script>
我可以看到正在执行的<script>
元素的注入代码(console.log()
函数输出Test)。
此外,如果我删除第一个空<script>
标记(从而使第一个元素[0]
引用脚本本身),则在DOM中更改脚本,但代码永远不会执行。< / p>
<script>
document.querySelectorAll("script")[0].innerHTML = 'console.log("Test")';
</script>
是什么促使这种行为?
答案 0 :(得分:4)
Scripting中对此进行了描述。当脚本为prepared时,
在第2步,&#34;解析器插入&#34;标志被删除:
如果元素设置了"parser-inserted"标志,则设置 is-parser-inserted 为true并取消设置元素的"parser-inserted"标记。
在第4步,恢复&#34;解析器插入&#34;标志,步骤被中止
如果元素没有
src
属性及其子节点if any,只包含注释节点和空Text
个节点 用户代理必须在此时中止这些步骤。脚本不是 执行。
因此,当您修改它时,它将再次准备好:
当
script
元素未标记为时 "parser-inserted"遇到了一个列出的事件 在以下列表中,用户代理必须同步preparescript
元素:
script
元素在inserted into a document之后根据DOM获得node is inserted之后 其他script
元素同时插入 早期Document
tree order中的script
。- in a
Document
元素为inserted,节点或文档片段为script
元素script
, 在当时的任何inserted元素script
之后。- in a
Document
元素为src
并且设置了script
属性,之前元素没有这样的属性 属性。
脚本运行后,修改内容不会执行它们,因为脚本准备将中止:
如果"already started"元素标记为{{3}},则用户代理必须在此处中止这些步骤 点。该脚本未执行。
答案 1 :(得分:2)
非常有趣的发现!
似乎空src-less script
元素处于一种奇怪的状态,它接受内容甚至是新的src
并解释它们。 (也无法找到原因。我只是有一个小小的暗示:)
类似于动态插入的脚本元素的行为。
以下是您观察的示例/证据,并添加了更多案例以供说明:
script[src]::before,
script {
display: block;
border: 1px solid red;
padding: 1em;
}
script[src]::before,
script {
content: 'src='attr(src)
}
button {
display: block
}
&#13;
<p>Existing empty script in HTML:</p>
<script id="existing"></script>
<p>Can be invoked just one of:</p>
<button onclick="eval(this.innerText)">
existing.innerHTML='console.log("innerHTML to static")'
</button>
<button onclick="eval(this.innerText)">
existing.src='data:text/javascript,console.log("src to static")'
</button>
<p>Dynamically created and inserted script (each creates own, so both work):</p>
<button onclick="eval(this.innerText)">
document.body.appendChild(document.createElement('script')).innerHTML='console.log("innerHTML to dynamic")'
</button>
<button onclick="eval(this.innerText)">
document.body.appendChild(document.createElement('script')).src='data:text/javascript,console.log("src to dynamic")'
</button>
&#13;
您必须重新运行代码段以查看&#34;静态&#34;案件有效。
(还有一个包含由SO生成的空白的空白脚本,无论出于何种原因。)
正如Laurianti所展示的那样,如果脚本有一些(甚至是空白的)内容(或src=""
),那么它就行不通了。
此外,在&#34;动态&#34;示例请注意,{/ 1}}或innerHTML
值在 src
元素插入文档后被更改。因此可以使用空白静态或创建动态脚本,将其保留在文档中并在此之后设置使用它。
很抱歉没有给出完整的答案,只是想分享研究和提示。
(更新删除; Oriol更快,更准确.Phew,很高兴看到这个整理好了!)
答案 2 :(得分:0)
如果更改innerHTML,则不会执行。你必须在追加它之前和之后写它。
var script = document.createElement("script");
script.innerHTML = 'console.log("Test");';
document.getElementsByTagName('head')[0].appendChild(script);
尝试添加新行:
<script>
</script>
<script>
document.querySelectorAll("script")[0].innerHTML = 'console.log("Test")';
</script>