JS BOM完全指南(二):事件轮询、三大尺寸家族与浏览器对象详解

前言

本文是BOM系列的第二篇,深入讲解JavaScript的事件轮询机制 (同步与异步的执行原理)、Location/Navigator/History三大浏览器对象 的详细用法,以及Offset、Client、Scroll三大尺寸家族的完整对比与应用。掌握这些内容,你将彻底理解JS的异步执行机制和页面尺寸测量的核心技术。


一、JS执行机制(事件轮询)

1.1 JS是单线程

JavaScript语言的一大特点就是单线程,也就是说,同一个时间只能做一件事。

为什么JS是单线程?因为JS最初是用来处理页面中用户的交互以及操作DOM而诞生的。如果同一时间做两件事,这两件事发生冲突就会导致错误。例如:鼠标移入又移出,同时又删除元素,浏览器就不知道应该执行哪个操作。

单线程的问题:所有任务需要排队,前一个任务结束才会执行后一个任务。如果JS执行时间过长,会造成页面渲染不连贯,导致页面加载阻塞。

1.2 同步与异步

为了解决单线程的性能问题,HTML5提出了Web Worker标准,允许JS脚本创建多个线程,于是JS中出现了同步和异步的概念。

概念 说明 生活类比
同步 前一个任务结束后再执行后一个任务,执行顺序与排列顺序一致 等水开了(10分钟后),再去切菜、炒菜
异步 做一件事时,因为花费时间长,同时可以去处理其他事情 烧水的10分钟内,去切菜、炒菜

1.3 同步任务与异步任务

任务类型 执行方式 执行场所
同步任务 在主线程上排队执行,前一个执行完毕才能执行后一个 主线程(执行栈)
异步任务 不进入主线程,进入"任务队列",通知主线程后才进入主线程执行 任务队列(消息队列)

常见的异步任务类型

类型 示例
定时器 setTimeoutsetInterval
DOM事件 clickresizeonload
ES6 Promise Promise.then()
Ajax异步请求 XMLHttpRequestfetch

1.4 JS执行机制(事件轮询 Event Loop)

核心流程

复制代码
┌──────────────┐
                   │   执行栈      │
                   │  (主线程)     │
                   └──────┬───────┘
                          │
              ┌───────────┴───────────┐
              │                       │
              ▼                       ▼
       ┌──────────────┐     ┌──────────────────┐
       │  同步任务     │     │   异步任务        │
       │  (立即执行)   │     │  (进入异步线程)   │
       └──────────────┘     └────────┬─────────┘
                                     │
                                     ▼
                            ┌──────────────────┐
                            │   任务队列        │
                            │  (等待执行)       │
                            └────────┬─────────┘
                                     │
                          主线程空闲时询问
                                     │
                                     ▼
                            ┌──────────────────┐
                            │   加入执行栈      │
                            └──────────────────┘

执行步骤说明

步骤 说明
执行栈开始顺序执行代码
判断任务是同步还是异步:同步立即执行,异步进入异步线程在任务队列等待
执行栈为空(同步任务执行完毕),询问任务队列中是否有异步任务需要执行
有则把任务加入执行栈末尾继续执行,没有则不停发起询问

经典示例

复制代码
setTimeout(function() {
    console.log("hello1");
}, 1000);

console.log(1);
console.log(2);

setTimeout(function() {
    console.log("hello2");
});

console.log(3);

// 输出顺序:1 → 2 → 3 → hello2 → hello1

分析

  1. 第一个setTimeout延迟1000ms,进入任务队列等待
  2. 同步任务依次输出1、2、3
  3. 第二个setTimeout延迟0ms(默认),先进入任务队列
  4. 同步任务执行完毕,检查任务队列,先取出第二个setTimeout输出"hello2"
  5. 1000ms后,第一个setTimeout到达时间,输出"hello1"

二、Location对象

2.1 常用属性

location对象管理当前页面的URL信息,可以直接通过location访问(等同于window.location)。

属性 说明 示例
location.href 返回当前加载页面的完整URL https://example.com/page?id=1#top
location.hash 返回URL中的hash(#号后内容) #top
location.host 返回服务器名称和端口号 example.com:8080
location.hostname 返回不带端口号的服务器名称 example.com
location.pathname 返回URL中的目录和文件名 /page/index.html
location.port 返回URL中指定的端口号 8080
location.protocol 返回页面使用的协议 https:
location.search 返回URL的查询字符串(?开头) ?id=1&name=test

2.2 常用方法

方法 功能 是否生成历史记录
location.assign(url) 跳转到新的页面(重定向) ✅ 有后退按钮
location.replace(url) 重新定向URL,替换当前页面 ❌ 无后退按钮
location.reload() 重新加载当前页面 ---
location.reload(true) 强制刷新(跳过缓存) ---
复制代码
// 跳转到百度
location.assign("https://www.baidu.com");

// 替换当前页面(不能后退)
location.replace("https://www.baidu.com");

// 刷新页面
location.reload();

// 强制刷新(跳过缓存)
location.reload(true);

三、Navigator对象

3.1 常用属性

navigator对象提供浏览器自身的信息。

复制代码
console.log(navigator.appName);     // Netscape(网景公司)
console.log(navigator.userAgent);   // 浏览器完整信息

3.2 浏览器类型判断

复制代码
if (/Chrome/i.test(navigator.userAgent)) {
    alert("谷歌浏览器");
} else if (/firefox/i.test(navigator.userAgent)) {
    alert("火狐浏览器");
} else if (/msie/i.test(navigator.userAgent)) {
    alert("IE浏览器");
} else if ("ActiveXObject" in window) {
    alert("你是IE(IE11特殊检测)");
} else {
    alert("其他浏览器");
}

四、History对象

history对象可以用来操作浏览器向前或者向后。

复制代码
// 获取历史记录数量
console.log(history.length);

// 后退一页
history.back();

// 前进一页
history.forward();

// 向前跳转一个页面
history.go(1);

// 向后跳转一个页面
history.go(-1);
方法 功能 等效操作
back() 后退一页 浏览器"后退"按钮
forward() 前进一页 浏览器"前进"按钮
go(n) 跳转n页(正数前进,负数后退) go(1) = forward()

五、Offset属性

5.1 offset概述

使用offset系列相关属性可以动态地得到该元素的位置(偏移)大小

特点

  • 获得元素距离带有定位祖先元素的位置
  • 获得元素自身的大小(宽度和高度)
  • 返回的数值都不带单位

5.2 offset常用属性

属性 作用
element.offsetParent 返回作为该元素带有定位的父级元素,如果父级没有定位则返回body
element.offsetTop 返回元素最左上角点相对于有定位父元素上方的偏移量
element.offsetLeft 返回元素最左上角点相对于有定位父元素左方的偏移量
element.offsetWidth 返回自身包括padding、边框、内容区的宽度(数值不带单位)
element.offsetHeight 返回自身包括padding、边框、内容区的高度(数值不带单位)
复制代码
var box = document.querySelector(".box");
var box1 = document.querySelector(".box1");

// 获取该元素带有定位的祖先级元素
console.log(box1.offsetParent);

// 返回元素相对于定位祖先元素上方的偏移量
console.log(box1.offsetTop);

// 返回元素相对于定位祖先元素左方的偏移量
console.log(box1.offsetLeft);

// 返回自身的宽度(包括内容区、边框、padding)
console.log(box.offsetWidth);

// 返回自身的高度(包括内容区、边框、padding)
console.log(box.offsetHeight);

六、Client属性

6.1 client概述

使用client系列的相关属性来获取元素可视区的相关信息,可以动态地得到该元素的边框大小、元素大小等。

6.2 client常用属性

属性 作用
element.clientTop 返回元素上边框的大小
element.clientLeft 返回元素左边框的大小
element.clientWidth 返回自身包括padding、内容区宽度,不含边框(数值不带单位)
element.clientHeight 返回自身包括padding、内容区高度,不含边框(数值不带单位)
复制代码
var box = document.querySelector(".box");

// 返回元素上边框大小
console.log(box.clientTop);   // 10

// 返回元素左边框大小
console.log(box.clientLeft);  // 10

// 返回自身的宽度,包括padding、内容区,不含边框
console.log(box.clientWidth); // 140

// 返回自身的高度,包括padding、内容区,不含边框
console.log(box.clientHeight); // 140

七、Scroll属性

7.1 scroll概述

利用scroll系列的相关属性可以动态地得到该元素的大小滚动距离

7.2 scroll常用属性

属性 作用
element.scrollTop 返回被卷去的上侧距离(数值不带单位)
element.scrollLeft 返回被卷去的左侧距离(数值不带单位)
element.scrollWidth 返回自身实际的宽度(实际内容的宽度+内边距),不含边框
element.scrollHeight 返回自身实际的高度(实际内容的高度+内边距),不含边框
复制代码
var box = document.querySelector(".box1");

// 返回自身实际的宽度(实际内容的宽度),不含边框
console.log("scrollWidth", box.scrollWidth);

// 返回自身实际的高度(实际内容的高度),不含边框
console.log("scrollHeight", box.scrollHeight);

// 返回被卷去的上侧距离
console.log("scrollTop", box.scrollTop);

// 返回被卷去的左侧距离
console.log("scrollLeft", box.scrollLeft);

7.3 滚动事件监听

复制代码
box.addEventListener("scroll", function() {
    console.log("scrollTop", box.scrollTop);
    console.log("scrollLeft", box.scrollLeft);
});

八、三大尺寸家族对比总结

8.1 核心对比表

属性系列 包含内容 应用场景
offset 内容 + padding + 边框 获取元素整体尺寸和位置
client 内容 + padding(不含边框) 获取元素可视区域尺寸
scroll 实际内容尺寸(含溢出部分) 检测滚动相关属性

8.2 offset与style的区别

对比项 offset style
样式来源 任意样式表(行内、内部、外部) 仅行内样式表
返回值类型 数值(不带单位) 字符串(带单位,如"100px")
包含内容 offsetWidth包含padding+border+width style.width不包含padding和border
读写权限 只读(只能获取,不能赋值) 可读写(可以获取也可以赋值)
适用场景 获取元素大小和位置 给元素更改样式值

8.3 三大系列属性速查

属性 包含边框 包含padding 包含内容 说明
offsetWidth/Height 元素整体尺寸
clientWidth/Height 可视区域尺寸
scrollWidth/Height ✅(含溢出) 实际内容尺寸
offsetTop/Left --- --- --- 相对于定位父级的偏移
clientTop/Left 边框本身 --- --- 边框宽度
scrollTop/Left --- --- --- 被卷去的距离

总结

本文系统梳理了JavaScript BOM第二部分和JS执行机制的完整知识体系:

主题 核心要点
JS执行机制 单线程、同步/异步、事件轮询(Event Loop)、任务队列
Location对象 href/hash/host/search属性、assign/replace/reload方法
Navigator对象 userAgent检测浏览器类型
History对象 back/forward/go操作历史记录
Offset系列 元素整体尺寸(含边框)+ 相对定位父级的偏移
Client系列 可视区域尺寸(不含边框)+ 边框大小
Scroll系列 实际内容尺寸 + 被卷去的距离 + 滚动事件监听

掌握这些内容,你就具备了操控浏览器行为和测量页面元素尺寸的完整能力。

相关推荐
technology_x22 分钟前
液冷超充站设备厂家哪家好?2026年功率与散热对比
java·开发语言
SurpriseDPD27 分钟前
bpftrace‑tasks 工具代码分析
开发语言·python
千谦阙听42 分钟前
C++篇:类和对象(上)
开发语言·c++
许彰午1 小时前
07-SqlBuilder六法
java·开发语言·低代码·架构
BS30813_vx1 小时前
【编号:01652】Spring Boot村务管理系统:财务公开、党建活动与计生服务一体化实战
开发语言·python
Jul1en_1 小时前
【Java 脚手架】封装通用工具类-3
java·开发语言·redis·缓存·ai·bootstrap·rabbitmq
学习星球1 小时前
2026年AI Agent全栈开发实战——从Prompt到Production
开发语言·人工智能·prompt
Fluxart.ai2 小时前
商品多角度图怎么做?Flux Art 从白底图到规格图、包装图的 10 步教程
开发语言·前端·javascript