0

我正在维护一个遗留的 javascript 应用程序,它的组件分为 4 个 JS 文件。

它们是“Default.aspx”、“set1.aspx”、“set2.aspx”和“set3.aspx”。ASPX 页面从属于它们各自集合的多个(所有不同的)源文件中写出压缩的 JS,并将内容类型标头设置为“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条线放在一个函数中,它就可以工作,否则就不行。发生了什么?

拆分和/或转义脚本文本不起作用。

4

4 回答 4

4

要查看问题,请查看其脚本元素中的第一行:

<script type="text/javascript">
    document.write('<script src="set1.aspx?v=1234" type="text/javascript"></script>');
</script>

因此,出现了一个 HTML 解析器并看到了开始的 <script> 标记。在 <script> 内部,普通的 <tag> 解析被禁用(在 SGML 术语中,元素具有 CDATA 内容)。为了找到脚本块的结束位置,HTML 解析器会查找匹配的关闭标记 </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 元素的字符序列实际上不是 '</tagname>' 而只是 '</' — 仍然存在于上一行中的序列。浏览器通常更宽容,实际上会允许它。

可能最好的解决方案是转义序列。有几种可能性,但最简单的是使用 JavaScript 字符串文字转义 ('\xNN'):

document.write('\x3Cscript src="set1.aspx?v=1234\x26w=5678" type="text/javascript"\x3E\x3C/script\x3E');

以上转义所有 '<', '>' 和'&' 字符,它不仅停止出现在字符串中的 '</' 序列,而且还允许将其插入到 XHTML 脚本块中而不会导致错误。

(在 XHTML 中,没有 CDATA 元素之类的东西,因此这些字符的含义与包含在正常内容中的含义相同,并且脚本块中的字符串 '<script>' 实际上会创建一个嵌套的脚本元素!这是可能的允许 <>& 在 XHTML 脚本块中使用 <![CDATA[ 部分,但它有点难看,通常最好避免在内联脚本中使用这些字符。)

于 2009-04-08T08:41:18.253 回答
1

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>
于 2009-04-08T06:17:42.497 回答
1

你也可以试试:

var script = document.createElement("script");
script.src = "set1.aspx?v=1234";
script.type = "text/javascript";
document.getElementsByTagName("head")[0].appendChild(script);

史蒂夫

于 2009-04-08T08:30:36.687 回答
0

如果您可以使用 JQuery,您可以使用以下内容:

$.getScript("set1.aspx?v=1234");

这会将脚本加载到全局 javascript 上下文中。确保将响应的内容类型设置为“text/javascript”。

希望这可以帮助...

于 2009-04-08T07:52:38.290 回答