页面加载后执行JavaScript的原理与实现方案

作者:小括号

时间:2026-10-25

浏览:151

本文解析浏览器页面加载流程及JS执行机制,指出JS与渲染线程互斥导致的空白或报错问题。对比window.onload、DOMContentLoaded及jQuery ready()的执行时机,推荐在DOM结构绘制完成后立即执行JS的方法,并提供原生JS封装思路,避免等待图片加载造成的延迟。

文章目录

浏览器页面加载流程与线程机制

页面加载过程具有明确的顺序,理解这一流程有助于优化脚本执行时机。

当用户在地址栏输入URL并回车后,浏览器开始处理请求。

  1. 首先检查本地hosts文件以获取域名对应的IP地址;若未找到,则发起DNS查询获取IP。
  2. 随后建立TCP连接,完成“三次握手”过程。
  3. 客户端向服务器发送HTTP请求。
  4. 服务端处理请求并将结果返回给客户端。
  5. 连接建立后,通过“四次挥手”关闭TCP连接。
  6. 浏览器接收响应并开始解析资源(JS、CSS、HTML),构建DOM树与CSSOM树,进而合并生成渲染树。
  7. 浏览器根据渲染树对页面进行最终渲染展示。

关于DOM树生成细节、握手过程中的具体行为以及CSSOM与DOM的对应关系,若不涉及底层系统开发,这些细节对本文主题影响不大。

获取结果后,浏览器渲染进程会启用多个线程协同完成页面渲染工作。

  • GUI渲染线程负责界面渲染、HTML/CSS解析、DOM与RenderObject树构建及布局绘制,界面回流时会触发此线程。
  • JS引擎线程负责执行脚本,该线程与GUI渲染线程互斥,执行JS时GUI线程会被挂起。
  • 事件触发线程依赖JS队列机制,将触发的事件添加至队尾等待JS引擎处理。
  • 定时器触发线程同样依赖JS队列机制运作。
  • 异步HTTP请求由独立的线程处理。

JS执行时机与潜在问题

关键机制在于:JavaScript执行线程与渲染线程互斥,且JS线程优先级最高。一旦HTML中出现<script>,浏览器会暂停其他元素显示,优先加载并执行JS代码。这可能导致两个问题:

  • 页面出现“一片空白”现象。
  • JS报错,因为脚本试图访问尚未加载完成的未知DOM内容。

推荐的JS执行方案对比

因此,需要一种机制来合理控制JS的执行时机。

许多人首选window.onload,但这并非最佳方案,因为它会等待页面所有资源(包括文字、表格、图片)加载完毕才触发,导致用户等待时间过长。若必须使用,更推荐DOMContentLoaded,该事件在文字加载完成后立即触发,无需考虑图片大小对初始加载时间的影响,前提是JS不依赖未加载的图片资源。

jQuery ready与原生实现原理

实际上,更理想的情况是让JS在“浏览器获取内容后、屏幕展示前”执行。jQuery提供了此类实现:

$(document).ready(function(){
	//...
})

据称jQuery的ready方法与原生JS的DOMContentLoaded效果一致,即在DOM结构绘制完成后立即执行(此时关联内容如图片可能未加载)。此外,JS中的window.onload与jQuery中的$(window).load()功能等价。

此处并非盲目推崇jQuery,开发者可自行封装类似功能。jQuery的ready()与JS的DOMContentLoaded均基于以下核心逻辑实现:

function init(){
	if(arguments.callee.done) return;
	arguments.callee.done=true;
	if(timer) clearInterval(timer);
	//...
}

//判断浏览器
//针对Mozilla/Opera9
if(document.addEventListener){
	document.addEventListener('DOMContentLoaded',init,false)
}
//针对IE
document.write ("<script id='__ie_onload defer' src='javascript:void(O);'><\/script>" );
var script = document.getElementById("__ie_onload");
script.onreadystatechange = function() {
	if( this.readyState == " complete" ) {
		init() //调用加截处理器
	};
}
//针对Safari 
if (/WebKit/i.test(navigator.userAgent)) {
	var timer = setinterval( function (){
		if( /loaded | complete/.test(document.readyState)) {
			init() //调用加载处理器
		}
}. 10);
//针对其他浏览器
window.onload = init;

以上介绍了页面加载后执行JavaScript的相关原理与方法,更多相关内容可参考本站其他文章。

实用工具推荐

电子包浆

绿化、压缩、噪点和虚拟水印,自由调节做旧程度。

使用 ›
图片压缩

选择画质和输出格式,预览压缩前后的大小。

使用 ›
相关文章