学前端也好,做 Web 安全也好,DOM 这关迟早要过。
很多人刚接触 JavaScript 时,最容易出现两种状态:
- 要么只会写语法,碰到页面元素就不会操作
- 要么会抄
document.getElementById(),但根本不知道为什么能拿到、什么时候拿不到
结果就是页面交互看不懂,前端逻辑跟不明白,做安全测试时看到 DOM XSS、节点注入、页面篡改这些词,也总觉得隔着一层。
今天这篇文章,我们就把 DOM 里最基础、也最关键的三块内容讲透:
- 什么是节点树
- DOM 常用属性到底能拿到什么
getElementById()为什么是前期最重要的 DOM 方法之一
一、先弄明白:DOM 到底是什么?
DOM,全称Document Object Model,中文叫文档对象模型。
你可以把它理解成一句最简单的话:
浏览器为了让 JavaScript 能操作网页,把整个 HTML 文档解析成一棵“对象树”。
这棵树里面,每个标签、每个层级关系,都可以被 JavaScript 找到并操作。
比如你写一段页面:
<!DOCTYPEhtml><html><head><title>测试页面</title></head><body><div>欢迎学习 DOM</div></body></html>浏览器不会把它当成“几行普通文本”来看,而是会把它组织成这样一棵结构:
- document
- html
- head
- title
- body
- div
- head
- html
这就是 DOM。
思维导图 1:什么是 DOM
二、节点树为什么这么重要?
因为网页里的标签,不是平铺在页面上的,它们是有层级关系的。
你可以把 HTML 看成一棵树:
- 最上面有根
- 根下面有分支
- 分支下面还有子分支
- 层层嵌套
例如这段代码:
<html><head><title>标题</title></head><body><div><p>这是段落</p></div></body></html>它的节点关系是:
html是最外层节点head和body是html的子节点title是head的子节点div是body的子节点p是div的子节点
这就是典型的节点树结构。
为什么一定要理解这点?
因为后面你做这些操作时,都离不开节点树的概念:
- 获取某个元素
- 判断父子关系
- 插入新节点
- 删除节点
- 分析数据最终进入了哪个位置
- 审计 DOM XSS 的 source 和 sink
你连树都没概念,后面一切都是乱的。
思维导图 2:节点树结构
三、DOM 里最常见的 4 个属性,必须先记住
刚接触 DOM 时,最常用、也最容易上手的,是下面这四个属性:
document.documentElementdocument.headdocument.titledocument.body
注意,它们都是document下面的属性。
也就是说,document 是整个页面的总入口。
四、document.documentElement:拿到真正的 html 根节点
这个属性的作用很明确:
获取页面中的<html>标签节点。
示例代码
<!DOCTYPEhtml><htmllang="zh-CN"><head><metacharset="UTF-8"><title>DOM 示例</title></head><body><h1>欢迎学习 DOM</h1></body></html>console.log(document.documentElement);console.log(document.documentElement.tagName);运行结果
<html lang="zh-CN">...</html>HTML这说明:
document.documentElement返回的是标签节点对象- 它拿到的就是页面里的
html元素
思维导图 3:document.documentElement
五、document.head:拿到 head 标签节点
这个属性用于获取<head>元素。
示例代码
console.log(document.head);console.log(document.head.tagName);运行结果
<head>...</head>HEAD注意这里一个细节:
它拿到的是整个<head>节点本身,不是内部某个子标签。
比如它不会直接替你拿到meta或title标签。
思维导图 4:document.head
六、document.title:这是文本,不是标签对象
这个点很容易出错,必须单独说。
结论先记住:
document.title获取的是网页标题文本,而不是<title>标签对象。
示例代码
<title>我的测试页面</title>console.log(document.title);运行结果
我的测试页面你看到没有?
打印出来的是标题内容,而不是:
<title>我的测试页面</title>更重要的是,它还能直接修改标题
document.title="标题已修改";console.log(document.title);运行结果
标题已修改同时浏览器标签页标题也会立刻变化。
完整案例
<