1 Document
1.1 浏览器环境,规格
1.1.1 整体结构
下图为JavaScript 在浏览器中运行时的结构图,Window 作为根对象,承担的两个角色:
window是JavaScript的全局对象;window是“浏览器窗口”,控制浏览器窗口的各种方法都绑定在window上。

1.1.2 Document Object Model
DOM是文档对象模型。利用DOM的概念,把网页中所有的内容都被表示为可以修改的对象。DOM规范解释了文档的结构,提供了操作文档的对象和方法,不仅支持浏览器,也对其他设备提供支持。
其中,Document对象是页面的主要“入口点”,可以使用它来更改或创建页面上的任何内容。
也就是说,
- JavaScript利用DOM操作页面的内容,不恰当的说,就是操作“HTML”部分;
- JavaScript利用CSSOM(CSS Object Model)操作页面的样式,也就是“CSS”部分,但是不常用。
1.1.3 Browser Object Model
BOM是浏览器对象模型。BOM的概念规定了主机环境(浏览器)除处理document(归BOM管)以外,所有内容以及这些内容的对象。
例如:
1.1.4 总结
以下是各个标准:
- DOM规范:描述文档的结构、操作和事件,详见 https://dom.spec.whatwg.org。
- CSSOM规范:描述样式表和样式规则,对它们进行的操作,以及它们与文档的绑定,详见 https://www.w3.org/TR/cssom-1/。
- HTML规范:描述 HTML 语言(例如标签)以及 BOM(浏览器对象模型)— 各种浏览器函数:
setTimeout,alert,location等,详见 https://html.spec.whatwg.org。它采用了 DOM 规范,并使用了许多其他属性和方法对其进行了扩展。
此 外,某些类被分别描述在 https://spec.whatwg.org/。
-
当你想要了解某个属性或方法时,使用Mozilla 手册 。
-
要查找某些内容时,可以使用互联网搜索 “WHATWG [term]” 或 “MDN [term]”,
例如 https://google.com?q=whatwg+localstorage,https://google.com?q=mdn+localstorage。
1.2 DOM树
在DOM文档对象模型中,HTML文档的主干是由一个个标签(tag)组成的,每个标签都声明为一个对象,这些标签对象和其他对象共同构成了一个DOM树结构。用JavaScript对对象进行修改,通过修改DOM文档,最终修改页面内容。
1.2.1 举例
一个简单的document,用HTML代码则表示如下结构。
<!DOCTYPE HTML>
<html>
<head>
<title>About elk</title>
</head>
<body>
The truth about elk.
</body>
</html>
如果用DOM模型的树形结构表示,可以想象为如下结构:

在HTML中的“标签(tag)”和其他元素,在DOM模型中则表示为“对象”,在树形结构中则称之为“节点”。
1.2.2 节点类型
**HTML 中的所有内容,都会成为 DOM 的一部分。**DOM中含有的节点类型,一共有[12种](DOM Standard (whatwg.org)):
// 摘录12种节点类型
const unsigned short ELEMENT_NODE = 1; // 元素节点(常见)
const unsigned short ATTRIBUTE_NODE = 2; // 属性节点(常见)
const unsigned short TEXT_NODE = 3; // 文本节点(常见)
const unsigned short CDATA_SECTION_NODE = 4; // CDATASection节点
const unsigned short ENTITY_REFERENCE_NODE = 5; // legacy EntityReference节点(历史)
const unsigned short ENTITY_NODE = 6; // legacy Entity节点(历史)
const unsigned short PROCESSING_INSTRUCTION_NODE = 7; // ProcessingInstruction节点
const unsigned short COMMENT_NODE = 8; // 注释节点(常见)
const unsigned short DOCUMENT_NODE = 9; // 文档节点(常见)
const unsigned short DOCUMENT_TYPE_NODE = 10; // DocumentType节点
const unsigned short DOCUMENT_FRAGMENT_NODE = 11; // 文档片段节点
const unsigned short NOTATION_NODE = 12; // legacy Notation节点(历史)
常见的节点类型为:
#document:Document node 文档节点,代表整个网页,是网页内容的入口,也是DOM树的根节点。#元素名:标签被称为 Element node 元素节点。<html>是根元素,也称为“顶级标签”,除此之外,还有子节点、父节点、兄弟节点等概念;#text:文本被称为 Text node文本节点,它一定被某个元素节点包含;#comment:Comment node 注释节点,即HTML代码中的注释部分,会被创建为一个注释节点;- ``:Attributes node 属性节点。对每一个元素设置的属性,都在创建的属性节点中保存。
1.2.3 特征
自动修正
和HTML的灵活性对应,当浏览器遇到不正确的HTML,会在形成DOM时自动更正它:
- 如果HTML中,没有顶级标签或
<body>标签,则形成DOM时自动创建<html>对象或<body>对象。 - 如果HTML中,有没有闭合的标签,则会自动闭合。
<p>xxx</p>
与控制台交互
在我们处理 DOM 时,我们可能还希望对其应用 JavaScript。例如:获取一个节点并运行一些代码来修改它,以查看结果。以下是在元素(Elements)选项卡和控制台(Console)之间切换的一些技巧。
首先,打开 elks.html:
- 在元素(Elements)选项卡中选择第一个
<li>。 - 按下 Esc — 它将在元素(Elements)选项卡下方打开控制台(Console)。
现在最后选中的元素可以通过 $0 来进行操作,先前选择的是 $1,等。
我们可以对它们执行一些命令。例如,$0.style.background = 'red' 使选定的列表项(list item)变成红色,像这样:

1.3 遍历DOM
修 改页面内容,就是通过对DOM进行操作;对 DOM 的所有操作,要先获取对应的DOM对象;获取DOM对象,都是以 document 对象开始。它是 DOM 的主“入口点”,从它我们可以访问任何节点。
对象之前存在一定的关系,就像上文提到的,有父节点、子节点、前驱节点、后继节点、第一个子节点、最后一个子节点等等。

可以看到,document对象是一个是最顶层节点。同时为了方便起见,把一些主要的元素节点地址,直接绑定在 document对象的属性中:
document.documentElement:指向<html>节点;document.body:指向<body>节点;document.head:指向<head>节点。
注:
document.body可能出现值为 null 的时候。出现这种情况是因为当要执行某段JavaScript代码,去读取document.body的时候,浏览器还尚未读取到<body>元素,所以只能返回“节点不存 在”。- 在 DOM 中,
null值就意味着“不存在”或者“没有这个节点”。
1.3.2 子节点
术语:
- 子节点:表示某节点的直系的子元素。
- 子孙元素:表示某节点下嵌套的所有元素,包括子元素,以及子元素的子元素等。
经常使用到的属性和方法:
childNodes集合:列出了所有子节点,包括文本节点。firstChild属性:访问第一个子元素。lastChild属性:访问最后一个子元素。elem.hasChildNodes()方法:检查节点是否有子节点。
1.3.3 DOM 集合
DOM 集合是一个类数组的可迭代对象,不是一个数组。其特点:
- 可迭代性。可以用
for...of迭代; - 不是数组。不可使用未继承的数组方法。(使用转换为数组、绑定数组方法变通)
- 只读。DOM 集合都是只读的,无法通过直接修改获取的
childNodes集合,来修改DOM树中的节点。 - 实时。除了特例,几乎所有的DOM集合都是实时的,反应了DOM的当前状态。
- 整理特例!
通常不会使用for...in 遍历,使用该方法,会便利该对象下所有可枚举(enumerable)的属性,会额外遍历出很少用的属性。
1.3.4 基本导航(navigation)属性
兄弟节点(Sibling) 是指有同一个父节点的节点。
某元素的导航(navigation)属性:
不区分节点类型:
-
访问后继兄弟节点:
elem.nextSibling -
访问前驱兄弟节点:
elem.previousSibling -
访问父节点:
elem.parentNode -
访问第一个子节点:
-
访问最后一个子节点:
只导航元素类型:
- 访问后继兄弟元素节点:
nextElementSibling - 访问前驱兄弟元素节点:
previousElementSibling - 访问父元素节点:
elem.parentElement - 访问第一个元素子节点:
elem.firstElementChild - 访问最后一个元素子节点:
elem.lastElementChild

注:
-
在绝大多数情况下,
elem.parentElement和elem.parentNode都会返回同一个父节点。例外的是,document.documentELement。根元素document.documentElement指向<html>,其父节点就是document根节点,但是#document不是一个元素节点,所以访问parentElement会返回null。document.documentElement.parentNode // document
document.documentElement.parentElement // null
1.3.4.1 表格(table)
表格节点拥有额外的导航属性:
<table> 拥有额外的属性:
table.rows:指向<tr>元素的集合;table.rows[i]:可访问第 i 个单元格。
table.caption:指向元素<caption>;table.tHead:指向元素<thead>;table.tFoot:指向元素<tfoot>;table.tBodies:指向<tbody>元素的集合。
<thead>,<tfoot>,<tbody> 元素提供了 rows 属性:
tbody.rows