Javascript外部脚本加载奇怪的问题

标签 javascript external-script

我正在维护一个旧版 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> 内部,正常的 解析被禁用(在 SGML 术语中,该元素具有 CDATA 内容)。为了找到脚本 block 的结束位置,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 元素的字符序列实际上并不是“”,而只是“

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

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

上面转义了所有'<'、'>'和'&'字符,这不仅阻止了'

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

关于Javascript外部脚本加载奇怪的问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/728697/

相关文章:

javascript - HTTPXmlRequest 返回空响应文本,状态为 0

javascript - 通过映射数组创建展平数组

drupal - 在 Drupal 6 的 <head> 中加载外部脚本

Javascript onload 和脚本回调函数,哪个优先?

python - 如何从另一个 python 脚本将本地 python 脚本执行到 docker 中?

javascript - 在 React.js 应用程序中从广告合作伙伴加载外部脚本

javascript - 我如何在 Joomla 站点中使用外部 HTML 表单?

javascript - 带有 ES6 模板字符串的 MongoDB 对象键

javascript - JS构造函数的返回值

angular - 如何将 3rd 方脚本从 Web 动态加载到 Angular2 组件中