Document.write(<script>) throws Unexpected token "ILLEGAL"

9
在你提问之前,我已经在Stack Overflow上搜索了很多次,并且通过Google搜索了无数次。我看到这里的任何其他情况都没有帮助过我。
让我们来看看我的问题:
我正在尝试在我的代码中使用以下脚本:
<script type='text/javaScript'>
    document.write("<script src='/feeds/posts/default/-/"+hom_cat1+"?max-results=1&orderby=published&alt=json-in-script&callback=showhomeposts1'></script>");
</script>

但我正在使用Blogger,它无法正确检测我的代码(请注意红色的脚本闭合标签):

note the red script closing tag

因此,我无法保存模板。所以我尝试使用website将我的代码转换为HTML实体。当我进行编码后,将其放入我的模板并保存,我会得到:

Uncaught SyntaxError: Unexpected token ILLEGAL 

这是我尝试使用的编码字符串:

&lt;script type='text/javaScript'&gt;document.write(&quot;&lt;script src='/feeds/posts/default/-/&quot;+hom_cat1+&quot;?max-results=1&amp;orderby=published&amp;alt=json-in-script&amp;callback=showhomeposts1'&gt;&lt;/script&gt;&quot;);&lt;/script&gt;

我该怎么做来解决我的问题?


只是想知道,为什么不直接将带有适当“src”的脚本标签插入文档中呢? - neoascetic
4个回答

27

问题在于传递给document.write的字符串包含字符</script>,这会导致document.write被调用的脚本元素过早地终止。

字符</script>不能出现在脚本中的任何位置,因为HTML解析器无法区分它与实际的</script>标签。

你可以尝试使用如下代码替代:

document.write("<script src='...'></scr" + "ipt>");

或者,如评论所述:

document.write("<script src='...'><\/script>");

另一个选择是使用DOM API创建script元素并将其插入到文档中。这里的其他答案提供了一些建议,但实现中存在潜在问题(例如,如果您尝试从head内部调用document.body.appendChild,它会抛出TypeError)。像这样做可能更为健壮:

(function() {
    var s = document.getElementsByTagName('script')[0];
    var script = document.createElement('script');
    script.src = 'http://something.com';
    s.parentNode.insertBefore(script, s);
}());

此外,type='text/javaScript' 是错误的;请使用 text/javascript 或省略 type 属性。


3
通常我建议在字符串中使用<\/script>,这样可以避免需要进行字符串连接的操作,但是很容易被忽略。 - zzzzBov
@zzzzBov,我以前也是这样做的,但 \/ 不是一个“真正”的转义,它只是一些可以工作的东西(就我从查看 ES5 第 7.8.4 节所知,反斜杠后面跟着不是转义字符或转义序列的一部分时没有定义任何行为)。 - Dagg Nabbit
1
@DaggNabbit “CharacterEscapeSequence :: NonEscapeCharacter 的 CV 是 NonEscapeCharacter 的 CV。”,这不是这种情况吗? - Fabrício Matté
@FabrícioMatté,你说得对,我想我没有往下读。所以这种行为在ES5中被定义了。我想知道它是否在ES3中被定义,因为有一段时间我决定\/不好用,现在我想知道为什么(现在我再次阅读它时,我看到它之前说过“CharacterEscapeSequence :: SingleEscapeCharacter NonEscapeCharacter”)。 - Dagg Nabbit
不,它也适用于ES3。也许\/是正确的方式。 - Dagg Nabbit
1
我曾经也认为这不太好,主要是因为它看起来像是一个笔误,下一个开发者可能会将其删除,然后系统就会出现问题(尽管我相信所有的替代方案都会有点“不对”,但在引起如此明显的问题之后按Ctrl+Z并不难)。无论如何,我只是想确保行为已经定义,因为H5BP仍然使用\/,这让我很好奇。=] - Fabrício Matté

4
您正在编写代码。
<script type='text/javaScript'>
    document.write("<script src='/feeds/posts/default/-/"+hom_cat1+"?max-results=1&orderby=published&alt=json-in-script&callback=showhomeposts1'></script>");
</script>

因此,输出将是一个位于另一个

1
不错的解决方案。尤其是第二个。 - Shell

2
更好的异步加载js的方式是这样的:
function loadScript () {

    var script = document.createElement('script');
    script.type = 'text/javascript';
    script.src = 'feeds/posts/default/your.js' 
    document.body.appendChild(script);

}

window.onload = loadScript;

如果您不需要任何功能,可以直接调用。

var script = document.createElement('script');
script.type = 'text/javascript';
script.src = 'feeds/posts/default/your.js' 
document.body.appendChild(script);

如google所建议的,也可以使用https://developers.google.com/maps/documentation/javascript/tutorial?hl=en#asynch

来进行异步处理。


0
如果你在使用Django,并且遇到了类似的问题:尝试这个:
<script src="{% static 'my/path/to/script.js' %}" ></script>

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接