Javascript 停止IE两次加载动态包含的脚本

Javascript 停止IE两次加载动态包含的脚本,javascript,jquery,internet-explorer,Javascript,Jquery,Internet Explorer,我在misc上包括一些相关内容。通过在标记末尾附近添加标记来加载网页,然后加载其他javascript文件。流程有点复杂,所以在提问之前,我会尝试解释一下: 浏览器在元素末尾附近加载带有元素的页面 script标记的src属性指向一个javascript文件,该文件(在某些情况下)注入第二个元素 注入的元素的src属性指向另一个javascript文件,该文件最终在页面的适当部分注入一些内容 我们使用这种两阶段方法,以便在决定是否包含最终内容之前能够进行一些基本处理,这可能需要一些时间来加载

我在misc上包括一些相关内容。通过在
标记末尾附近添加
标记来加载网页,然后加载其他javascript文件。流程有点复杂,所以在提问之前,我会尝试解释一下:

  • 浏览器在
    元素末尾附近加载带有
    元素的页面
  • script标记的src属性指向一个javascript文件,该文件(在某些情况下)注入第二个
    元素
  • 注入的
    元素的src属性指向另一个javascript文件,该文件最终在页面的适当部分注入一些内容
我们使用这种两阶段方法,以便在决定是否包含最终内容之前能够进行一些基本处理,这可能需要一些时间来加载

问题是IE8(可能还有更早的版本)会加载最后一个javascript两次。设置src属性的行为似乎会触发加载,但将脚本标记附加到DOM中也会触发加载。有没有办法避免这种情况


我对这个问题提出了一个新的看法。如果您有某种跟踪HTTP请求的方法,您将看到IE8加载js_test2.js两次。

似乎jquery正在使用XmlHttpRequest获取js_test2的第二个实例


为什么我不知道,但这是您需要调查的JQuery的行为。

我看到在类似情况下(例如克隆
节点)在IE的其他版本上发生了这种行为,我从来都不知道如何阻止脚本执行两次,因此,我最后做的是在脚本代码上添加一个保护,使其不会运行两次。有点像:

if (typeof(loaded) == 'undefined') {
    // the whole code goes in here
    var loaded = true;
}

如果无法找到防止脚本执行两次的方法,您可能希望尝试这种方法。

在加载脚本之前,您可以检查文档中是否已存在脚本-

function fetchscript(url, callback){
 var S= document.getElementsByTagName('script'), L= S.length;
 while(L){
  if(S[--L].src== url) return true;
 }
 //create and append script and any callbacks
}

根本区别在于IE在第一次将脚本元素添加到父元素的子节点时执行脚本元素,而不管父元素是否实际在文档中。其他浏览器仅在脚本添加到文档的子节点树中的节点时执行脚本

jQuery的
domManip
函数(jQuery 1.3.2的第524行)由
append
和其他类似的jQuery方法调用,它试图变得更聪明,并为它在最终解析的HTML中找到的
元素调用
evalScript
,以执行脚本(如果需要外部脚本,则通过执行AJAX请求)。(实际的脚本元素已从已解析的子节点中删除,以阻止在插入文档时执行这些元素,因此当包含它们的内容一次附加到多个元素中时,脚本只执行一次。)

但是,由于前面的
clean
函数在解析HTML时将脚本元素附加到包装器div,IE将已经执行了脚本。所以你被处决了两次

最好的做法是,在使用脚本执行任何操作时,避免将
domManip
函数(如
append
)与HTML字符串一起使用

事实上,忘记将内容放入序列化的HTML字符串中并让jQuery对其进行解析;只需使用更可靠的普通DOM方式即可:

var s= document.createElement('script');
s.type= 'text/javascript';
s.charset= 'UTF-8';
s.src= 'js_test2.js';
document.getElementById('some_container').appendChild(s);
(老实说,在查看了
clean
函数的源代码后,我对使用jQuery的基于HTML字符串的DOM操作进行任何操作都有严重的怀疑。它应该可以修复浏览器错误,但在我看来,笨拙的正则表达式处理可能会导致与它解决的问题一样多的问题。)

顺便说一句,在最初的通话中:

document.write(unescape("%3Cscript src='js_test1.js' type='text/javascript'%3E%3C/script%3E"));

你不需要在这里退场;我不知道为什么这么多人这么做。序列
这可能是因为您使用了
文档。当您已经在
元素中时编写
。您是否尝试过将
附加到
而不是
文档。编写

我发现同样的问题,只发生在IE中

jQuery的
html()
方法链是:
html>append>domManip>clean

clean()
method use
innerHTML
make string to DOM,IE中的
innerHTML
有一个bug,
script
标记将立即加载(第一次加载),jQuery
evalScript
脚本标记位于
domManip
方法(ajax加载)的末尾。然后在IE中加载两次脚本文件


我认为jQuery应该解决这个问题,更新clean()方法,这很奇怪,但似乎你是对的。如果我使用appendChild而不是jQuery的append,它不会加载js_test2.js两次。我想如果我做了演示/真的/赤裸裸的(没有jQuery),我自己就会发现这一点。谢谢我做了一些调查。结果(如下)不太好。谢谢你给出了非常详尽的答案。我确实回到了更传统的DOM方式,现在它工作得很好。关于第一次调用中的逃避:如果我没记错的话,我复制了Google Analytics用来包含脚本的代码,前提是(可能是错误的)假设,如果有人知道如何可靠地包含远程javascript,那就是GA人员。感谢您的澄清。awesome试图找到一种方法来检查是否定义了一个全局变量,当然在脚本运行之前不会将其定义为false。谢谢
document.write('\x3Cscript src="js_test1.js" type="text/javascript">\x3C/script>"));