Javascript外部脚本加载异常
Posted
技术标签:
【中文标题】Javascript外部脚本加载异常【英文标题】:Javascript external script loading strangeness 【发布时间】:2009-04-08 05:59:18 【问题描述】:我正在维护一个遗留的 javascript 应用程序,它的组件被分成 4 个 JS 文件。
它们是“Default.aspx”、“set1.aspx”、“set2.aspx”和“set3.aspx”。 ASPX 页面从属于它们各自集合的多个(所有不同的)源文件中写出压缩的 JS,并将 content-type 标头设置为“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)中都没有任何错误。
但是,由于我一直在安静地编写这个脚本,所以我想在很多地方简化函数调用并错误地内联上面的 Script 函数,导致以下代码:
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
行放在函数中,它可以工作,否则就不行。发生了什么事?
拆分和/或转义脚本文本不起作用。
【问题讨论】:
您需要仔细检查包含和评估 javascript 文件的顺序。如果您可以发布文档大纲可能会有所帮助。 @Salman A 我今晚会做...有点复杂。 修改了整个问题......希望它能让事情更清楚 【参考方案1】:要查看问题,请查看其脚本元素中的第一行:
<script type="text/javascript">
document.write('<script src="set1.aspx?v=1234" type="text/javascript"></script>');
</script>
于是出现了一个 html 解析器并看到了开始的 。
它找到的第一个是字符串文字中的那个。 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脚本块中而不会导致错误.
(在 XHTML 中,没有 CDATA 元素这样的东西,因此这些字符与包含在正常内容中的含义相同,并且脚本块中的字符串 '
【讨论】:
加载器脚本位于它自己的 JS 文件中。 不在 HTML 页面正文中。 啊,“内联”这个词在当时具有误导性。然后您需要向我们展示完整的代码(最好:作为在线演示);我们无法从上面孤立的 sn-ps 猜测您执行脚本的顺序。 全局级别的 document.write() 没有理由与立即执行的函数中的行为不同,因此可能有其他问题。 @bobnice 确实......这就是我发布 SO 问题的原因。今晚我会找时间重写这个问题。谢谢!【参考方案2】:1) 确保在脚本“实际”包含在您的页面中之前不要尝试引用 MyApp。
2) 尝试在您的内联加载器中打破“脚本”一词,如下所示:
<script type="text/javascript">
document.write('<scr' + 'ipt src="set1.aspx?v=1234" type="text/javascript"></scr' + 'ipt>');
</script>
或者,使用我从谷歌分析代码中借用并能够成功使用的语法:
<script type="text/javascript">
document.write(unescape("%3Cscript src='set1.aspx?v=1234' type='text/javascript'%3E%3C/script%3E"));
</script>
【讨论】:
试过了,不行。请看编辑。不过,谷歌分析代码是一个不错的技巧。【参考方案3】:你也可以试试:
var script = document.createElement("script");
script.src = "set1.aspx?v=1234";
script.type = "text/javascript";
document.getElementsByTagName("head")[0].appendChild(script);
史蒂夫
【讨论】:
试过了,但问题仍然存在。只有当我把它放在函数体中时它才会起作用。【参考方案4】:如果您可以使用 JQuery,您可以使用以下内容:
$.getScript("set1.aspx?v=1234");
这会将脚本加载到全局 javascript 上下文中。 确保将响应的内容类型设置为“text/javascript”。
希望这会有所帮助...
【讨论】:
谢谢...但 jQuery 不是一个选项。以上是关于Javascript外部脚本加载异常的主要内容,如果未能解决你的问题,请参考以下文章
WKWebView 是不是支持加载外部 javascript 文件?
从 Angular 组件动态加载外部 javascript 文件
《JavaScript 高级程序设计》读书笔记二 使用JavaScript