我正在维护一个旧版 JavaScript 应用程序,其组件分为 4 个 JS 文件。
它们是“Default.aspx”、“set1.aspx”、“set2.aspx”和“set3.aspx”。 ASPX 页面从属于各自集合的多个(完全不同的)源文件中写出压缩的 JS,并将内容类型 header 设置为“text/javascript”。
通过添加对第一组的引用并创建主条目对象来调用应用程序。
<script src="/app/default.aspx" type="text/javascript"></script>
<script type="text/javascript>
var ax;
// <body onload="OnLoad()">
function OnLoad() {
ax = new MyApp(document.getElementById("axTargetDiv"));
}
</script>
第一组脚本 (default.aspx) 的末尾是以下准确代码:
function Script(src) {
document.write('<script src="' + src + '" type="text/javascript"></script>');
}
Script("set1.aspx?v=" + Settings.Version);
这会加载第二组脚本 (set1.aspx)。并且这在所有主要浏览器(IE6-8 Firefox Safari Opera Chrome)中都不会出现任何错误。
但是,由于我一直在安静地编写这个脚本,所以我想在很多地方简化函数调用,并错误地内联了上面的脚本函数,导致了以下代码:
document.write('<script src="set1.aspx?v=' + Settings.Version + '" type="text/javascript"></script>');
当使用测试页面进行测试时,现在会在所有浏览器中引发以下错误:
MyApp is not defined.
这发生在以下行:ax = new MyApp(...
,因为 Visual Studio JS 调试器和 Firebug 报告了它。
我在这个问题的前4个答案中尝试了各种方法,但没有成功。唯一能让 MyApp 成功加载的方法就是将实际的“添加脚本”代码放入函数中(即 document.write('script')
行):
如果我将 document.write
行放在函数内,它就可以工作,否则就不会。发生什么事了?
分割和/或转义脚本文本不起作用。
最佳答案
要查看问题,请查看其脚本元素中的顶行:
<script type="text/javascript">
document.write('<script src="set1.aspx?v=1234" type="text/javascript"></script>');
</script>
因此 HTML 解析器出现并看到开始的 <script> 标记。在 <script> 内部,正常的
它找到的第一个是字符串文字中的那个。 HTML 解析器无法知道它在字符串文字中,因为 HTML 解析器不了解 JavaScript 语法,它们只了解 CDATA。所以你实际上想说的是:
<script type="text/javascript">
document.write('<script src="set1.aspx?v=1234" type="text/javascript">
</script>
即,未闭合的字符串文字和未完成的函数调用。这些会导致 JavaScript 错误,并且永远不会写入所需的脚本标记。
解决该问题的常见尝试是:
document.write('...</scr' + 'ipt>');
这在技术上仍然是错误的(并且无法验证)。这是因为在 SGML 中,结束 CDATA 元素的字符序列实际上并不是“”,而只是“” — 仍然存在于上面的行中的序列。浏览器通常更宽容,并且在实践中会允许它。
也许最好的解决方案是转义序列。有几种可能性,但最简单的是使用 JavaScript 字符串文字转义 ('\xNN'):
document.write('\x3Cscript src="set1.aspx?v=1234\x26w=5678" type="text/javascript"\x3E\x3C/script\x3E');
上面转义了所有'<'、'>'和'&'字符,这不仅阻止了''序列出现在字符串中,而且还允许将其插入到XHTML脚本 block 中而不会导致错误.
(在 XHTML 中,不存在 CDATA 元素之类的东西,因此这些字符与包含在普通内容中的含义相同,并且脚本 block 内的字符串“<script>”实际上会创建一个嵌套脚本元素!可以通过使用 <![CDATA[ 部分来允许在 XHTML 脚本 block 中使用 <>&,但这有点难看,通常最好避免在内联脚本中使用这些字符。)
关于Javascript外部脚本加载奇怪的问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/728697/