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

特殊字符u2028导致的Javascript脚本异常

Hight Performance Javascript——脚本加载和运行

javascript脚本异步加载的几种方式