今天(2026年)的浏览器环境已经比2013年的时候好太多了,本站目前就自我实现了document.ready方法,比那时候的方式简洁太多了,也更好用,有兴趣的朋友可以打开console调试。
什么是 document.ready?
说 document.ready 之前,先要讲讲 window.onload。
我们知道,如果在网页头部执行获取或者修改 DOM 结构的操作,一般需要把相关代码放到 window.onload 中。
为什么需要这样操作呢?
看看下面这个例子:
<!DOCTYPE HTML>
<html lang="en">
<head>
<script>
vara=document.getElementById("demo");
alert(a);
</script>
</head>
<body>
<div id="demo">DEMO</div>
</body>
</html>
当执行 "alert(a)" 时,会弹出 null 这实际上说明 document.getElementById() 没有找到对应的对象。
为什么呢?因为 JavaScript 代码执行的时候,后面的 DOM 结构还没有加载出来。
这里的代码执行顺序大概是:
为了解决这个问题,我们可以使用 window.onload。
onload 可以让我们在整个页面加载完成之后,再执行相关 JavaScript 代码。
例如:
window.onload =function(){
va ra=document.getElementById("demo");
alert(a);
};这样执行的时候,页面中的 DOM 已经加载完成,就不会出现找不到对象的问题了。
window.onload的问题
问题又来了。现代网页中不可避免地会使用图片等其他资源。如果网页中存在比较大的图片,那么可能出现这样的情况:
网页的 DOM 结构已经加载完成了,但是图片还在下载。
这时候,window.onload 仍然不会执行。
也就是说,虽然我们的 JavaScript 已经可以操作 DOM 了,但是由于图片还没有下载完成,onload 里的代码还不能执行。
对于很多前端代码来说,我们其实并不需要等待图片下载完成,只要 HTML 的 DOM 结构已经准备好,就可以开始执行 JavaScript。
因此,为了让 JavaScript 在 DOM 加载完成之后尽快执行,一般可以有两种方法。第一种方法比较简单,就是直接把 JavaScript 代码放到相关 HTML 标签之后。
例如:
<divid="demo">DEMO</div>
<script>
va ra=document.getElementById("demo");
alert(a);
</script>
这样执行 JavaScript 的时候,#demo 已经出现在 DOM 中了。
第二种方法,就是判断 DOM 结构是否已经加载完成。用过 jQuery 的人应该都知道,它提供了:
$(document).ready(...)
这样的方法,可以在 DOM 加载完成之后执行相关代码。
今天的目的,就是自己实现一个类似 jQuery document.ready() 的方法。
自己实现 document.ready
先来看完整代码:
<!DOCTYPE HTML>
<html lang="en">
<head>
<script>
var $= (function(){
var ready = function(callback){
if(document.addEventListener){
document.addEventListener("DOMContentLoaded", function(){
document.removeEventListener("DOMContentLoaded", arguments.callee, false);
callback();
}, false);
}else if(document.attachEvent){
document.attachEvent("onreadystatechange", function(){
if(document.readyState ==="complete"){
document.detachEvent("onreadystatechange", arguments.callee);
callback();
}
}
);
}
}
return {
ready: ready
}
})();
$.ready(function(){
alert(document.getElementById("demo").innerHTML);
});
</script>
</head>
<body>
<divid="demo">DEMO</div>
</body>
</html>
写好 $ 这个对象之后,我们就可以通过它提供的 ready 方法来判断 DOM 是否已经加载完成,然后执行传入的回调函数。
使用起来和我们平时使用 jQuery 的方式比较接近:
$.ready(function(){
alert(document.getElementById("demo").innerHTML);
});主要原理
这个方法的主要原理,就是监听 DOM 加载完成的事件。
现代浏览器可以使用:
document.addEventListener("DOMContentLoaded", callback, false);当 DOM 结构加载完成之后,就执行我们的回调函数。
而对于较老版本的 IE 浏览器,则使用:
document.attachEvent("onreadystatechange",callback);然后判断:
document.readyState ==="complete"
如果页面已经加载完成,就执行回调函数。
所以整个过程可以简单理解为:
和:
相比,这种方法关注的是 DOM 是否已经准备好,而不是等待页面中的所有资源都加载完成。
addEventListener 和 attachEvent
这里再简单说一下这两个方法。
addEventListener 支持 IE9+(包括 IE9)的浏览器。
它接受三个参数:eventType, handler和useCapture
第一个参数是事件类型,例如:DOMContentLoaded,第二个参数是事件处理函数,第三个参数一般设置为 false
而 attachEvent 用于较老版本的 IE 浏览器。它和 addEventListener 有一些区别。
首先,它只接受两个参数:
其次,事件名称需要带上 on
例如:onreadystatechange,而使用 addEventListener 时则不需要:DOMContentLoaded
这也是为什么上面的代码需要根据不同浏览器分别处理。
通过这种方式,我们就可以自己实现一个比较简单的 document.ready(),在 DOM 结构加载完成之后执行需要操作 DOM 的 JavaScript 代码。
评论0
欢迎分享你的看法,也欢迎补充不同的实践经验。