第 3 章 DOM
文档:DOM中的“D”
摘抄
当创建了一个网页并把它加载到Web浏览器中时,DOM就在幕后悄然而生。它把你编写的网页文档转换为一个文档对象。
在人类语言中,“对象”这个词的含义往往不那么明确,它几乎可以用来称呼任何一种东西。但在程序设计语言中,“对象”这个词的含义非常明确。
评论
划重点,DOM将我们编写的网页文档转换为一个文档对象。也就是没有太阳怎么会有阳光呢?没有太阳怎么会有发射阳光的动作呢?
对象:DOM中的“O”
摘抄
你应该还记得,“对象”是一种自足的数据集合。与某个特定对象相关联的变量被称为这个对象的属性;只能通过某个特定对象去调用的函数被称为这个对象的方法。
评论
文档对象应该有它自己的属性和方法。对象可以由多种基本数据类型组合起来。比如,黄子涵是一个对象,那么黄子涵的年龄、身高等等是这个对象的属性,通过黄子涵这个对象所产生的动作也就是调用函数,比如,黄子涵唱歌、黄子涵做饭等等,也就是这个对象的方法。
对象的分类
摘抄
JavaScript语言里的对象可以分为三种类型。
- 用户定义对象(user-defined object):由程序员自行创建的对象。
- 内建对象(native object):内建在JavaScript语言里的对象,如Array、Math 和Date等。
- 宿主对象(host object):由浏览器提供的对象。
即使是在JavaScript的最初版本里,对编写脚本来说非常重要的一些宿主对象就已经可用了,它们当中最基础的对象是window对象。
评论
了解一下JavaScript中的三种对象类型。其实,宿主对象应该是JavaScript语言独有的,像其他两种的那样有类似的情况,用户自定义的函数和C语言自带的库函数。
BOM
摘抄
window对象对应着浏览器窗口本身,这个对象的属性和方法通常统称为BOM(浏览器对象模型),但我觉得称为Window Object Model(窗口对象模型)更为贴切。BOM提供了window.open和window.blur等方法,这些方法某种程度上要为到处被滥用的各种弹出窗口和下拉菜单负责。难怪JavaScript会有一个不好的名声!
值得庆幸的是,我们不需要与BOM打太多的交道,而是把注意力集中在浏览器窗口内的网页内容上。document对象的主要功能就是处理网页内容。
评论
血压一下子上来,原来浏览器的弹窗都是这个通过这个对象搞出来的,“是兄弟就来砍我!”,以前真的是,这种弹窗真的是烦死人。
模型:DOM中的“M”
摘抄
DOM中的“M”代表着“Model”(模型),但说它代表着“Map”(地图)也未尝不可。模型也好,地图也罢,它们的含义都是某种事物的表现形式。就像一个模型火车代表着一列真正的火车、一张城市街道图代表着一个实际存在的城市那样,DOM代表着加载到浏览器窗口的当前网页。浏览器提供了网页的地图(或者说模型),而我们可以通过JavaScript去读取这张地图。
既然是地图,就必须有诸如方向、等高线和比例尺之类的图例。要想看懂和使用地图,就必须知道这些图例的含义和用途,这个道理同样适用于DOM。要想从DOM获得信息,必须先把各种表示和描述文档的“图例”弄明白。
DOM把一份文档表示为一棵树(这里所说的“树”是数学意义上的概念),这是我们理解和运用这一模型的关键。更具体地说,DOM把文档表示为一棵家谱树。
家谱树本身又是一种模型。家谱树的典型用法是表示一个人类家族的谱系,并使用parent(父)、child(子)、sibling(兄弟)等记号来表明家族成员之间的关系。家谱树可以把一些相当复杂的关系简明地表示出来:一位特定的家族成员既是某些成员的父辈,又是另一位成员的子辈,同时还是另一位成员的兄弟。
家谱树模型非常适合用来表示一份用(X)HTML语言编写出来的文档。
评论

其实说的和数据结构中的树没啥区别,就拿上面的蜘蛛图片也可以看做中心点为根节点的树。想象一下,按照上面的说法,JavaScript就像这只蜘蛛,我们可以通过这只蜘蛛寻找在蜘蛛网上的猎物。
元素节点、属性节点、文本节点之间的关系
摘抄
评论
元素节点包含着属性节点和文本节点,一个元素节点可以构成一棵树,但是一个元素节点也可以包含其他元素节点,类似于数据结构中的树的概念。
继承
摘抄
类似于DOM,CSS也把文档的内容视为一棵节点树。节点树上的各个元素将继承其父元素的样式属性。
评论
下面通过一个实验验证上面的这段话:
实验代码
<!DOCTYPE html> <html lang="zh"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <style> #box1 { width: 300px; height: 300px; border: 5px solid red; background-color: skyblue; } #box2 { width: 200px; height: 200px; border: 5px solid yellow; } #box3 { width: 100px; height: 100px; border: 5px solid green; } </style> </head> <body> <div id="box1"> <div id="box2"> <div id="box3"></div> </div> </div> </body> </html>
实验截图
实验总结
你会看到我给box1添加了一个背景颜色,box2和box3都继承了这个背景颜色。
获取元素
getElementById
摘抄
document.getElementById(id)
这个调用将返回一个对象,这个对象对应着document 对象里的一个独一无二的元素,那个元素的HTML id 属性值是purchases 。你可以用typeof 操作符来验证这一点。typeof 操作符可以告诉我们它的操作数是一个字符串、数值、函数、布尔值还是对象。
实验代码
<!DOCTYPE html> <html lang="zh"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>测试</title> <style> #box1 { width: 300px; height: 300px; border: 5px solid red; background-color: skyblue; } #box2 { width: 200px; height: 200px; border: 5px solid yellow; } #box3 { width: 100px; height: 100px; border: 5px solid green; } </style> </head> <body> <div id="box1"> <div id="box2"> <div id="box3"></div> </div> </div> <script> alert(typeof document.getElementById("#box1")); </script> </body> </html>
实验截图
getElementsByTagName
摘抄
document.getElementsByTagName("li")这个调用将返回一个对象数组,每个对象分别对应着document 对象中的一个列表项元素。与任何其他的数组一样,我们可以利用length 属性查出这个数组里的元素个数。
实验代码
<!DOCTYPE html> <html lang="zh"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>测试</title> <style> #box1 { width: 300px; height: 300px; border: 5px solid red; background-color: skyblue; } #box2 { width: 200px; height: 200px; border: 5px solid yellow; } #box3 { width: 100px; height: 100px; border: 5px solid green; } </style> </head> <body> <div id="box1"> <div id="box2"> <div id="box3"> <ul class="box3-ul"> <li>1</li> <li>2</li> <li>3</li> </ul> </div> </div> </div> <script> console.log("box3-ul的长度:" + document.getElementsByTagName("box3-ul").length); console.log("**********************li元素数组*************************"); var liItems = document.getElementsByTagName("li"); console.log("li元素:" + liItems.length); console.log("li元素的长度:" + liItems); for(var i = 0;i < liItems.length;i++) { console.log("li元素数组中的元素:" + liItems[i]); console.log("查看数组中元素的数据类型:" + typeof liItems[i]); } console.log("**********************div元素数组*************************"); var divItems = document.getElementsByTagName("div"); console.log("div元素:" + divItems) console.log("div元素的长度:" + divItems.length); for(var j = 0;j < divItems.length;j++) { console.log("div元素数组中的元素:" + divItems[j]); console.log("查看数组中元素的数据类型:" + typeof divItems[j]); } console.log("************************所有元素****************************"); var Items = document.getElementsByTagName("*"); console.log("所有元素:" + Items) console.log("所有元素的长度:" + Items.length); console.log("************************box3下的所有元素****************************"); var box3 = document.getElementById("box3"); var box3All = box3.getElementsByTagName("*"); console.log("box3下的所有元素:" + box3All) console.log("box3下的所有元素的长度:" + box3All.length); </script> </body> </html>
实验截图
getElementsByClassName
摘抄
getElementsByClassName(class)
这个方法的返回值也与getElementsByTagName 类似,都是一个具有相同类名的元素的数组。
实验代码
<!DOCTYPE html> <html lang="zh"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>测试</title> <style> .box1 { width: 300px; height: 300px; border: 5px solid red; background-color: skyblue; } .box2 { width: 200px; height: 200px; border: 5px solid yellow; } .box3 { width: 100px; height: 100px; border: 5px solid green; } </style> </head> <body> <div class="box1"> <div id="box2"> <div class="box3"> <ul id="box3-ul"> <li>1</li> <li>2</li> <li>3</li> </ul> </div> </div> <div class="box4"></div> <div class="box4"></div> <div class="box4"></div> <div class="box4"></div> <div class="box5"></div> <div class="box5"></div> <div class="box5"></div> <div class="box5"></div> <div class="box5"></div> </div> <script> var box1 = document.getElementsByClassName("box1"); console.log("box1的长度:" + box1.length); var box4 = document.getElementsByClassName("box4"); console.log("box4的长度:" + box4.length); var box5 = document.getElementsByClassName("box5"); console.log("box5的长度:" + box5.length); var box2 = document.getElementById("box2"); console.log("box3的长度:" + box2.getElementsByClassName("box3").length); </script> </body> </html>
实验截图
获取和设置属性
getAttribute
摘抄
getAttribute 是一个函数。它只有一个参数——你打算查询的属性的名字:
object.getAttribute(attribute) 与此前我们介绍过的那些方法不同,getAttribute 方法不属于document 对象,所以不能通过document 对象调用。它只能通过元素节点对象调用。例如,可以与getElementsByTagName 方法合用,获取每个
<p>
元素的title 属性。
实验代码
<!DOCTYPE html> <html lang="zh"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>测试</title> </head> <body> <div class="box" id="box" title="黄子涵是帅哥!"> <div class="box" title="黄子涵是靓仔!"> <div class="box" title="黄子涵真聪明!"> <ul class="box" title="黄子涵真厉害!"> <li>1</li> <li>2</li> <li>3</li> </ul> </div> </div> <div class="box4"></div> <div class="box4"></div> <div class="box4"></div> <div class="box4"></div> <div class="box5"></div> <div class="box5"></div> <div class="box5"></div> <div class="box5"></div> <div class="box5"></div> </div> <script> console.log("******************获取box的title属性******************"); var box1 = document.getElementsByClassName("box"); for(var i = 0; i < box1.length; i++) { console.log(box1[i].getAttribute("title")); } console.log("******************获取属性时返回null******************"); var li = document.getElementsByTagName("li"); for(var i = 0; i < li.length; i++) { console.log(li[i].getAttribute("title")); } console.log("******************有值时才返回属性******************"); var box2 = document.getElementById("box"); var title = box2.getAttribute("title"); if(title != null) { console.log(title); } </script> </body> </html>
实验截图
setAttribute
摘抄
setAttribute() 有点不同:它允许我们对属性节点的值做出修改。与getAttribute 一样,setAttribute 也只能用于元素节点:
object.setAttribute(attribute,value)
实验代码
<!DOCTYPE html> <html lang="zh"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>测试</title> </head> <body> <div id="box" title="黄子涵是帅哥!"> <ul id="ul"> <li title="黄子涵是靓仔!"></li> <li title="黄子涵是靓仔!"></li> <li title="黄子涵是靓仔!"></li> </ul> </div> <script> console.log("*************修改title属性值****************"); var box = document.getElementById("box"); console.log(box.getAttribute("title")); box.setAttribute("title", "黄子函是靓仔!") console.log(box.getAttribute("title")); console.log("*************修改li属性值****************"); var li = document.getElementsByTagName("li"); for(var i = 0; i < li.length; i++) { li[i].setAttribute("title","黄子涵真聪明!"); console.log(li[i].getAttribute("title")); } </script> </body> </html>
实验截图
一个细节
摘抄
通过setAttribute 对文档做出修改后,在通过浏览器的view
source(查看源代码)选项去查看文档的源代码时看到的仍将是改变前的属性值,也就是说,setAttribute 做出的修改不会反映在文档本身的源代码里。这种“表里不一”的现象源自DOM的工作模式:先加载文档的静态内容,再动态刷新,动态刷新不影响文档的静态内容。这正是DOM的真正威力:对页面内容进行刷新却不需要在浏览器里刷新页面。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?