Javascript外部脚本加载陌生感 [英] Javascript external script loading strangeness
问题描述
我正在维护一个遗留的javascript应用程序,它的组件分为4个JS文件。
I'm maintaining a legacy javascript application which has its components split into 4 JS files.
它们是Default.aspx,set1.aspx, set2.aspx和set3.aspx。 ASPX页面从属于其各自集合的多个(所有不同的)源文件中写出压缩的JS,并将内容类型标题设置为text / javascript。
They are "Default.aspx", "set1.aspx", "set2.aspx" and "set3.aspx". The ASPX pages writes out compressed JS from multiple (all-different) source files belonged to their respective set and set content-type header to "text/javascript".
通过添加对第一个集的引用并创建主条目对象来调用application。
The application is invoked by adding a reference to the first set and creating the main entry object.
<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)的末尾是以下 exact 代码:
At the end of the first set of scripts (default.aspx) is the following exact code:
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)。
Which loads the second set of scripts (set1.aspx). And this works without any errors in all major browsers (IE6-8 Firefox Safari Opera Chrome).
然而,由于我一直在努力安静这个脚本,我想简化函数调用在很多地方并错误地内联了上面的Script函数,产生了以下c颂歌:
However, as I've been working on this script for quiet sometime, I'd like to simplify function calls in a lot of places and mistakenly inlined the above Script function, resulting in the following code:
document.write('<script src="set1.aspx?v=' + Settings.Version + '" type="text/javascript"></script>');
当使用测试页面测试时,现在会在所有浏览器中抛出以下错误:
Which, when tested with a test page, now throws the following error in all browsers:
MyApp is not defined.
这行发生在以下行: ax = new MyApp(...
作为Visual Studio JS调试器和 Firebug报告它。
This happens at the line: ax = new MyApp(...
as Visual Studio JS debugger and Firebug reports it.
我在前4个答案中尝试了各种方法只有将实际的添加脚本代码放在一个函数中(即 document.write('script')才能使MyApp成功加载才能使这个问题无效。 code> line):
I've tried various methods in the first 4 answers posted to this question to no avail. The only thing that will enable MyApp to loads successfully is only by putting the actual "add script" code inside a function (i.e. the document.write('script')
line):
如果我在函数中放入 document.write
行,它有效,否则,它没有。发生了什么?
If I put the document.write
line inside a function, it works, otherwise, it doesn't. What's happening?
分割和/或转义脚本文本不起作用。
Splitting and/or escaping the script text does not work.
推荐答案
要查看问题,请查看其脚本元素中的第一行:
To see the problem, look at that top line in its script element:
<script type="text/javascript">
document.write('<script src="set1.aspx?v=1234" type="text/javascript"></script>');
</script>
因此,HTML解析器出现并看到了开头的< script>标记。在< script>内部,正常< tag>解析被禁用(在SGML术语中,元素具有CDATA内容)。为了找到脚本块的结束位置,HTML解析器会查找匹配的close-tag< / script>。
So an HTML parser comes along and sees the opening <script> tag. Inside <script>, normal <tag> parsing is disabled (in SGML terms, the element has CDATA content). To find where the script block ends, the HTML parser looks for the matching close-tag </script>.
它找到的第一个是字符串中的一个文字。 HTML解析器无法知道它在字符串文字中,因为HTML解析器对JavaScript语法一无所知,他们只知道CDATA。所以你实际上说的是:
The first one it finds is the one inside the string literal. An HTML parser can't know that it's inside a string literal, because HTML parsers don't know anything about JavaScript syntax, they only know about CDATA. So what you are actually saying is:
<script type="text/javascript">
document.write('<script src="set1.aspx?v=1234" type="text/javascript">
</script>
即未封闭的字符串文字和未完成的函数调用。这些会导致JavaScript错误,并且永远不会写入所需的脚本标记。
That is, an unclosed string literal and an unfinished function call. These result in JavaScript errors and the desired script tag is never written.
解决问题的常见尝试是:
A common attempt to solve the problem is:
document.write('...</scr' + 'ipt>');
这在技术上仍然是错误的(这是因为在SGML中,结束CDATA元素的字符序列实际上不是'< / tagname>'而只是'< /' - 一个仍然存在于上面一行中的序列。浏览器通常更宽容,并且在实践中允许它。
This is still technically wrong (and won't validate). This is because in SGML, the character sequence that ends a CDATA element is not actually ‘</tagname>’ but just ‘</’ — a sequence that is still present in the line above. Browsers generally are more forgiving and in practice will allow it.
可能最好的解决方案是逃避序列。有一些可能性,但最简单的是使用JavaScript字符串文字转义符('\ xNNN'):
Probably the best solution is to escape the sequence. There are a few possibilities, but the simplest is to use JavaScript string literal escapes ('\xNN'):
document.write('\x3Cscript src="set1.aspx?v=1234\x26w=5678" type="text/javascript"\x3E\x3C/script\x3E');
上述内容包含所有'<','>'和'&'字符,其中不仅停止出现在字符串中的'< /'序列,而且还允许它插入到XHTML脚本块中而不会导致错误。
The above escapes all ‘<’, ‘>’ and ‘&’ characters, which not only stops the ‘</’ sequence appearing in the string, but also allows it to be inserted into an XHTML script block without causing errors.
(在XHTML中,没有CDATA元素这样的东西,所以这些字符与正常内容中包含的含义相同,脚本块中的字符串'< script>'实际上会创建一个嵌套的脚本元素!可以允许< ;>&在XHTML脚本块中使用<![CDATA [部分,但它有点难看,通常最好避免在内联脚本中使用这些字符。)
(In XHTML, there's no such thing as a CDATA element, so these characters would have the same meaning as if included in normal content, and a string '<script>' inside a script block would actually create a nested script element! It's possible to allow <>& in an XHTML script block by using a <![CDATA[ section, but it's a bit ugly and usually better to avoid using those characters in inline script.)
这篇关于Javascript外部脚本加载陌生感的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!