前言
在浏览器中,document 对象是我们的老朋友。它是整个 HTML 页面的根节点,也是我们访问页面元素、获取文档状态的唯一入口。深入理解 document,不仅能帮你写出更优雅的 DOM 操作代码,更是掌握浏览器原理的基础。
一、 Document 节点的身份属性
document 是 window 对象的一个属性,作为一个全局对象存在。
nodeType: 9nodeName: documentparentNode: null(它是整棵树的顶端)
二、 文档结构的快捷访问
为了提高效率,document 提供了一些直接访问核心元素的“快捷键”,无需通过 ID 查找。
| 属性 | 返回内容 | 说明 |
|---|---|---|
document.documentElement | <html> 元素 | 文档的最外层容器 |
document.head | <head> 元素 | 包含元数据、脚本和样式定义 |
document.body | <body> 元素 | 包含页面的可见内容 |
三、 文档信息与状态属性
1. 基础信息
-
document.title:读写页面标题(浏览器标签页显示的文本)。 -
document.URL:当前页面的完整 URL(只读)。 -
document.referrer:来源页面的 URL。常用于统计用户是从哪个网站跳转过来的。 -
document.readyState:loading:文档正在加载。complete:文档解析完成(可以进行交互)。
2. 特殊属性:document.domain
核心用途:解决基础的跨子域通信。
- 逻辑:如果
a.example.com和b.example.com都将document.domain设置为example.com,它们就可以突破同源策略进行 JS 交互。 - 限制:只能设置为当前域名或其父域名;且只能修改一次。
⚠️ 注意:现代浏览器出于安全考虑,已逐渐弃用
document.domain来跨域,建议优先使用postMessageAPI。
四、 元素查找:传统 vs 现代
1. 传统查找方法(返回实时集合)
这些方法返回的通常是 HTMLCollection,会随 DOM 的改变而实时更新。
getElementById(id): 返回匹配 ID 的第一个元素(大小写敏感)。getElementsByTagName(tag): 根据标签名获取元素,返回标签数组。getElementsByClassName(cls): 根据class获取元素,返回包含指定类名的元素。
2. 现代查询方法(推荐使用)
这些方法接收 CSS 选择器参数,语法更灵活,功能更强大。
querySelector(selector): 根据接受的css选择参数name来查找元素,返回匹配该选择器的第一个元素。querySelectorAll(selector):跟 querySelector()一样,也接收一个用于查询的参数,返回所有匹配的节点列表(NodeList)。
// 获取所有具有 username 和 current 两个类名的元素
let list = document.querySelectorAll(".username.current");
// 甚至可以进行复杂的层级查找
let activeLinks = document.querySelectorAll("nav > ul li.active a");
五、 面试模拟题
Q1:document.documentElement 和 document.body 有什么区别?
参考回答:
documentElement 始终指向 HTML 文档的根元素 <html>,而 body 指向 <body>。在计算滚动高度时,标准模式下通常使用 documentElement.scrollTop,而混杂模式下可能需要使用 body.scrollTop。
Q2:querySelector 和 getElementById 哪个性能更好?
参考回答:
getElementById 性能更高。它是为 ID 查找专门优化的,执行路径单一。querySelector 需要解析复杂的 CSS 选择器。但在现代浏览器中,这种性能差异在绝大多数场景下可以忽略不计,querySelector 的灵活性更有优势。
Q3:如何判断文档是否已经加载完成?
参考回答:
可以通过监听 readystatechange 事件,并判断 document.readyState === 'complete';或者直接监听 DOMContentLoaded(DOM 构建完成)和 load(所有资源加载完成)事件。