代码之家  ›  专栏  ›  技术社区  ›  futtta

Opera中的javascript范围问题?

  •  4
  • futtta  · 技术社区  · 14 年前

    我有一个类似HTML+javascript的小部件,人们可以一次或多次复制/粘贴到他们的HTML页面中。该块检查外部javascript文件是否已经在DOM中,如果不在,则加载它,如下所示:

    (function(){
      d = document;
      if (!d.getElementById('ex-scr')) {
        scr = d.createElement('script');
        scr.async = true;
        scr.id = 'ex-scr';
        scr.src = 'external.js';
        d.getElementsByTagName('head')[0].appendChild(scr)
      }
    })();
    

    外部javascript文件检查HTML页面上的小部件实例(使用getelementsbyclassname),并对这些实例执行类似的操作;

    for (var i=0;i<document.getElementsByClassName('target').length;i++) {
     document.getElementsByClassName('target')[i].style.borderStyle="solid";
    }
    

    这方面的一个工作示例可以在 http://futtta.be/opera_enigma.html .

    这在Firefox(3.6&4b)、Chrome(5&6)和Safari中非常有效,但在Opera(在最新版本10.61中测试)中无法正常工作:无论有多少“小部件”(在 class='target' )由于nodelist只包含1个条目(长度为1而不是2、3或…),因此opera只对第一个条目起作用。

    如果在小部件的javascript中,我调用函数用window.onload加载外部脚本,那么问题就消失了,但是我希望我的小部件尽快激活(不干扰页面的其余部分,因此是异步的东西)。

    所以我的问题是:我的代码中是否存在一个被Firefox、Safari和Chrome忽略的错误?这是歌剧里的虫子吗?我怎样才能让歌剧表演?

    2 回复  |  直到 14 年前
        1
  •  5
  •   Pekka    14 年前

    如果在小部件的javascript中,我调用函数用window.onload加载外部脚本,问题就会消失。

    我想这就是你的问题所在。当 getElementsByClassName 在脚本文件中执行,但还不能保证DOM完全存在。你不需要等到 DOMready loaded 事件。

        2
  •  1
  •   hallvors    14 年前

    您可能在浏览器之间遇到了一个小的时间差异:如果您通过DOM向文档头添加一个脚本,Opera当前将等到脚本执行后再分析文档的其余部分。这是我在这里写的第三期: http://my.opera.com/hallvors/blog/2009/03/07/websites-playing-timing-roulette

    其他主要浏览器将在等待外部脚本时继续解析。当外部脚本进入时,它们将运行外部脚本,其中 随机 (取决于缓存、文档大小、连接速度等)可能会使它在所有要操作的元素都在DOM中时运行。但是,我可以保证,在您之前尝试查找DOM中某个类型的所有元素 知道 分析完整标记会给任何浏览器中的某些用户带来问题-您所做的是对小型网络中断、连接速度差异、CPU电源以及在加载和分析网页时影响时间的所有其他细微差异过于敏感。

    浏览器给你两个信号,页面已经准备好编写脚本了:domcontentloaded事件和onload。如果需要从文档或其元素中读取维度,则可能需要等到加载了所有图像和CSS(即等待onload事件),否则可以使用domcontentloaded。jquery提供了$(document.ready()来抽象出浏览器支持的“dom is ready now”信号中的差异,其他框架可能也有相同的信号。