javascript 模拟JQuery的Ready方法实现并出现的问题

  dom加载完后执行,一直不了解,基于对网上的一些方法逻辑不了解,所以去看了《jquery源代码研究(ready函数) 》这篇文章后自己写入如下代码(已有详细说明)

  

复制代码 代码如下:

  <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

  <html xmlns="http://www.w3.org/1999/xhtml">

  <head>

  <meta http-equiv="Content-Type" content="text/html; charset=gb2312" />

  <title>document.ready</title>

  <script type="text/javascript" src="js/jquery-1.3.2.js"></script>

  <script type="text/javascript">

  var Darren;

  (function(){

  var isReady=false; //是否已经加载完毕

  var readBound=false; //判断是否已经调用过循环事件

  var readylist=[]; //把需要执行的方法先暂存在这个数组里

  //判断浏览器,该方法来自Cloudgamer JavaScript Library v0.1

  var Browser = (function(ua){

  var b = {

  msie: /msie/.test(ua) && !/opera/.test(ua),

  opera: /opera/.test(ua),

  safari: /webkit/.test(ua) && !/chrome/.test(ua),

  firefox: /firefox/.test(ua),

  chrome: /chrome/.test(ua)

  };

  var vMark = "";

  for (var i in b) {

  if (b[i]) {

  vMark = i;

  }

  }

  if (b.safari) {

  vMark = "version";

  }

  b.version = RegExp("(?:" + vMark + ")[\\/: ]([\\d.]+)").test(ua) ? RegExp.$1 : "0";

  b.ie = b.msie;

  b.ie6 = b.msie && parseInt(b.version) == 6;

  b.ie7 = b.msie && parseInt(b.version) == 7;

  b.ie8 = b.msie && parseInt(b.version) == 8;

  return b;

  })(window.navigator.userAgent.toLowerCase());

  function bindReady()

  {

  if(readBound){ //保证bindReady方法只执行一遍

  return;

  }

  readBound=true;

  //For IE并且不是嵌套在frame中

  if (Browser.msie && window==top)

  {

  (function(){

  if (isReady) {

  return;

  }

  try {

  document.documentElement.doScroll("left"); //如果没加载dom完毕这个会报错

  }

  catch (error) {

  setTimeout(arguments.callee, 0); //循环调用父函数,也就是ready方法

  return;

  }

  Test.Done();

  })();

  }else if(Browser.firefox)//For FF

  {

  document.addEventListener( "DOMContentLoaded", Test.Done, false );

  }

  }

  var Test={

  ready:function(fn){

  bindReady();//判断是否加载完毕

  if(isReady)

  {

  fn.call(document); //加载完毕,直接调用

  }else{

  readylist.push(fn);//如果还没加载完成则将该方法暂存到readylist数组中,以便以后调用

  }

  return this;

  }

  };

  //静态方法:加载完毕执行

  Test.Done=function(){

  if (!isReady) {

  isReady=true;

  }

  readylist[0].call(document);

  }

  Darren=Test;

  })();

  //测试

  Darren.ready(function(){

  alert("my");

  document.getElementById("test").innerHTML="haha" //成功读取dom

  });

  $(function(){alert("jq")});

  window.onload=function(){alert("default")}

  </script>

  </head>

  <body>

  <div id="test">test</div>

  </body>

  </html>

  由于要和jq做对比,所以测试时候需要导入jq库。函数本身是没有调用jq的,请放心引用。

  代码我通过封装完成,直接Darren.ready(fn)就可执行。

  后来通过测试还是出现一个奇怪的问题:在FF下的执行顺序是jq -> my -> load 。也就是说我这个函数能够在onload事件执行前触发,但会晚于jq的ready。对这个还是比较满意。

  但是在IE下测试居然是:jq -> load -> my。也就是 我的这个函数虽然能够把代码提前,但是还是在onload事件执行后触发的,百思不得其解。

  完同志们解答下如何实现onload之前执行,jq又是怎么实现的,我完全模拟jq的结构,但是还是不能达到目的,难道中间有漏?

  另大家可以参考下面的代码

  

复制代码 代码如下:

  var ready=function(readyCall) {

  if(document.addEventListener)

  document.addEventListener("DOMContentLoaded",function() {

  document.removeEventListener("DOMContentLoaded",arguments.callee,false);

  readyCall();

  },false);

  else if(document.attachEvent) {//for IE

  if(document.documentElement.doScroll && window.self==window.top) {

  (function() {

  try {

  document.documentElement.doScroll("left");

  }catch(ex) {

  setTimeout(arguments.callee,5);

  return;

  }

  readyCall();

  })();

  }else {//maybe late but also for iframes

  document.attachEvent("onreadystatechange",function() {

  if(document.readyState==="complete") {

  document.detachEvent("onreadystatechange", arguments.callee);

  readyCall();

  }

  });

  }

  }

  }