Javascript窗口/图像onload计时 - 这应该不起作用,但确实如此

时间:2013-11-16 18:45:48

标签: javascript

这是一个加载两个图像的简单程序,将第二个图像放在第一个图像的顶部,然后使用setInterval和不透明度更改淡入或淡出顶部图像。它运行得很完美,虽然查看代码,如果在topPic(竞争条件)之前加载botPic,它应该会失败。但它没有,我也无法弄清楚它为什么没有。

  window.onload = function() {
    var topPic = document.getElementById("topPic");
    var botPic = document.getElementById("botPic");
  }

  function findPosition(obj) {
    var curleft = 0;
    var curtop = 0;
    if (obj.offsetParent) {
      do {
        curleft += obj.offsetLeft;
        curtop += obj.offsetTop;
      } while ((obj = obj.offsetParent) !== null);
    }
    return [curleft, curtop];
  }

  function doTopPicLoad() {
    topPicLoaded = 1;
    if (botPicLoaded == 1) {
      startFader();
    }
  }

  function doBotPicLoad() {
    var leftTop = findPosition(botPic);
    topPic.style.left = leftTop[0];
    topPic.style.top  = leftTop[1];
    botPicLoaded = 1;

    if (topPicLoaded == 1) {
      startFader();
    }
  }

  function startFader() {
    // do stuff
  }

  <img id="botPic" onload='doBotPicLoad()' src="DMH_0991-M-72-720x576.jpg">
  <img id="topPic" onload='doTopPicLoad()' src="DMH_0991-72-720x576.jpg">

通过console.log或插入DOM进行记录,始终显示&#34; window.load&#34;作为最后执行的项目。 doTopPicLoad和doBotPicLoad以各种顺序出现,但它们总是将topPic和botPic显示为有效对象。

topPic.onload [object HTMLImageElement] [object HTMLImageElement]
botPic.onload [object HTMLImageElement] [object HTMLImageElement]
startFader
window.onload

但是,如果我这样开始,它通常(总是?)失败。

var topPic;
var botPic;

window.onload = function() {
  topPic = document.getElementById("topPic");
  botPic = document.getElementById("botPic");
}

我唯一的想法:

Javascript解释器&#34;知道&#34;它必须延迟执行任何引用window.onload函数内声明的任何vars的语句 - 直到该函数完成。 (这似乎很牵强,但它可以解释它。)

我不想在我的代码中留下竞争条件,但似乎没有任何实际的&#34;种族&#34;发生。任何人都可以解释为什么这段代码总是有效吗?

实际例子: http://www.davehennessey.com/photography/small-buildings/DMH_0991X2.html

谢谢 - 戴夫

2 个答案:

答案 0 :(得分:0)

您的窗口“加载”处理程序正在设置两个本地变量。您的脚本直接引用“topPic”和“botPic”<img> DOM元素。如果这两行没有以var开头,事情就不会真正改变,因为“topPic”和“botPic”已经已经指的是那些将被那些人返回的值致电.getElementById()

也就是说,当你的代码(在窗口“load”处理程序之外)引用变量“topPic”和“botPic”时,它所访问的是通过这些名称绑定到窗口对象的DOM元素。浏览器会这样做,因为元素具有那些“id”值。

因为在<img>元素“加载”事件触发之前不会调用函数,所以事情有效。 (在加载图像之前设置<img>元素的“样式”将正常工作。)您的窗口“加载”处理程序是多余的,根本不会影响系统。

答案 1 :(得分:0)

Pointy指出,你的topPic和botPic变量只对匿名onload函数是本地的,不会影响页面的其余部分。

您是否考虑过定义Pic类?

function Pic(elem) {
  this.elem = elem;
  this.loaded = false
}

// define global objects topPic and botPic that have elem and loaded attributes

window.onload = function() {
    topPic = new Pic(document.getElementById("topPic"));
    botPic = new Pic(document.getElementById("botPic"));
  }

  function findPosition(obj) {
    var curleft = 0;
    var curtop = 0;
    if (obj.offsetParent) {
      do {
        curleft += obj.offsetLeft;
        curtop += obj.offsetTop;
      } while ((obj = obj.offsetParent) !== null);
    }
    return [curleft, curtop];
  }

  function doTopPicLoad() {
    topPic.loaded = true;
    if ( botPic.loaded ) {
      startFader();
    }
  }

  function doBotPicLoad() {
    var leftTop = findPosition(botPic.elem);
    topPic.elem.style.left = leftTop[0];
    topPic.elem.style.top  = leftTop[1];
    botPic.loaded = true;

    if ( topPic.loaded ) {
      startFader();
    }
  }

  function startFader() {
    // do stuff
  }