数字营销 · Web开发 · 基础设施

怎么样实现 jQuery 的 document.ready 方法

通过实现 jQuery 的 $(document).ready(),理解其实现原理和 Web 代码执行顺序,并了解 DOM 加载与页面性能之间的关系。
今天(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 结构还没有加载出来。

这里的代码执行顺序大概是:

执行 JavaScript
查找 #demo
#demo 还没有解析出来
返回 null

为了解决这个问题,我们可以使用 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 加载
检测 DOM 是否完成
执行 callback

和:

window.onload

相比,这种方法关注的是 DOM 是否已经准备好,而不是等待页面中的所有资源都加载完成。

addEventListener 和 attachEvent

这里再简单说一下这两个方法。

addEventListener 支持 IE9+(包括 IE9)的浏览器。

它接受三个参数:eventType, handler和useCapture

第一个参数是事件类型,例如:DOMContentLoaded,第二个参数是事件处理函数,第三个参数一般设置为 false

而 attachEvent 用于较老版本的 IE 浏览器。它和 addEventListener 有一些区别。

首先,它只接受两个参数:

eventType,
handler

其次,事件名称需要带上 on

例如:onreadystatechange,而使用 addEventListener 时则不需要:DOMContentLoaded

这也是为什么上面的代码需要根据不同浏览器分别处理。

通过这种方式,我们就可以自己实现一个比较简单的 document.ready(),在 DOM 结构加载完成之后执行需要操作 DOM 的 JavaScript 代码。

评论0

欢迎分享你的看法,也欢迎补充不同的实践经验。