节点层次
Node类型
DOM1级定义了一个Node接口,该接口由DOM中的所有节点类型实现。这个Node接口在JavaScript中是作为Node类型实现
JavaScript中所有节点类型都继承自Node类型,因此所有节点类型都共享着相同的基本属性和方法
每个节点都有一个nodeType属性,用于表明节点的类型
Node.ELEMENT_NODE(1)---表示元素节点
Node.ATTRIBUTE_NODE(2)---表示属性节点
Node.TEXT_NODE(3)---表示文本节点
Node.CDATA_SECTION_NODE(4)---表示文档中的 CDATA 部分
Node.ENTITY_REFERENCE_NODE(5)---表示实体引用
Node.ENTITY_NODE(6)---表示实体
Node.PROCESSING_INSTRUCTION_NODE(7)---表示处理指令
Node.COMMENT_NODE(8)---表示注释
Node.DOCUMENT_NODE(9)---表示整个文档(DOM 树的根节点)
Node.DOCUMENT_TYPE_NODE(10)---表示向为文档定义的实体提供接口
Node.DOCUMENT_FRAGMENT_NODE(11)---表示代表轻量级的 Document 对象,能够容纳文档的某个部分
Node.NOTATION_NODE(12)---表示DTD 中声明的符号
节点关系
每个节点都有一个childNodes属性,其中保存着一个NodeList对象
NodeList是一种类数组对象,用于保存一组有序的节点,可以通过位置来访问这些节点
NodeList并不是Array的实例
NodeList对象实际上是基于DOM结构动态执行查询的结果,因此DOM结构的变化能够自动反映在NodeList对象中
可以通过方括号或者item()方法访问保存在NodeList中的节点
length属性表示的是访问NodeList的那一刻,其中包含的节点数量
使用Array.prototype.slice()方法可以将NodeList对象转换为数组
每个节点都有一个parentNode属性,该属性指向文档树中的父节点
父节点的firstChild和lastChild属性分别指向列表中的第一个和最后一个节点
hasChildNodes()方法在节点包含一或多个子节点的情况下返回true
所有节点都有一个ownerDocument属性,该属性指向整个文档的文档节点。通过这个属性,可以直接访问文档节点,而不必在节点层次中通过层层回溯到达顶端
操作节点
appendChild()方法
用于向childNodes列表的末尾添加一个节点
返回新增的节点
insertBefore()方法
可以把节点放在childNodes列表中某个特定的位置上
接收两个参数:要插入的节点和作为参照的节点
replaceChild()方法
接受两个参数:要插入的节点和要替换的节点
返回要替换的节点
removeChild()方法
接受一个参数,即要移除的节点
返回被移除的节点
通过removeChild()移除的节点仍然为文档所有,只不过在文档中已经没有了自己的位置
cloneNode()方法
用于创建调用这个方法的节点的一个完全相同的副本
接收一个布尔值参数,表示是否执行深复制
在参数为true的情况下,执行深复制,也就是复制节点及整个子节点树;在参数为false的情况下,执行浅复制,即只复制节点本身。复制后返回的节点副本属于文档所有,但并没有为它指定父节点,因此,这个节点副本就成了一个孤儿,除非通过appendChild()、insertBerfore()或replaceChild()将它添加到文档中
只会复制特性、(在明确指定的情况下也复制)子节点
normalize()方法
用于处理文档树中的文本节点
如果找到了空文本节点,则删除它,如果找到相邻的文本节点,则将它们合并为一个文本节点
Document类型
在浏览器中,document对象是HTMLDocument(继承自Document类型)的一个实例,表示整个HTML页面
document对象是window对象的一个属性,因此可以将其作为全局对象来访问
特征
nodeType的值为9
nodeName的值为#document
nodeValue的值为null
parentNode的值为null
ownerDocument的值null
其子节点可能是一个DocumentType(最多一个)、Element(最多一个)、ProcessingInstruction或Comment
文档的子节点
documentElement属性
始终指向HTML页面中的<html>元素
childNodes属性
可以访问文档元素
body属性
指向<body>元素
doctype属性
访问<!DOCTYPE>中的信息
文档信息
作为HTMLDocument的一个实例,document对象还有一些标准的Document对象所没有的属性。这些属性提供了document对象所表现的网页的一些信息
title属性
包含着<title>元素中的文本
URL属性
包含页面完整的URL
不可以设置
domain属性
只包含页面的域名
可以设置
不能将这个属性设置为URL中不包含的域
referrer属性
保存着链接到当前页面的那个页面的URL
不可以设置
查找元素
getElementById()方法
接收一个参数:要取得的元素的ID
如果找到相应的元素则返回该元素,如果不存在则返回null
如果页面中多个元素的ID值相同,getElementById()只返回文档中第一次出现的元素
getElementsByTagName()方法
接收一个参数:即要取得元素的标签名
返回的是包含零或多个元素的NodeList
HTMLCollection对象
在HTML文档中,这个方法会返回一个HTMLCollection对象,作为一个动态集合,该对象与NodeList非常相似
可以使用方括号语法或item()方法来访问HTMLCollection对象中的项
这个对象中元素的数量则可以通过其length属性取得
使用namedItem()方法可以通过元素的name特性取得集合中的项
HTMLCollection还支持按名称访问项,对命名的项也可以使用方括号语法来访问,可以向方括号中传入数值或字符串形式的索引值,在后台,对数值索引就会调用item(),对字符索引就会调用namedIten()
要想取得文档中所有元素,可以向getElementsByTagName()中传入*
getElementsByName()方法
只有HTMLDocument类型才有的方法
返回带有给定name特性的所有元素,也是HTMLCollection对象
特殊集合
document.anchors:包含文档中所有带name特性的<a>元素
document.forms:包含文档中所有的<form>元素
document.images:包含所有的<img>元素
document.links:包含文档中所有带href特性的<a>元素
这些集合都是HTMLCollection对象
DOM一致性检测
document.implementation属性
检测浏览器实现了DOM的哪些部分
hasFeature()方法
接收两个参数:要检测的DOM功能的名称及版本号
如果浏览器支持给定名称和版本功能,则该方法返回true
hasFeature()返回true有时候不意味着实现与规范一致,建议在使用DOM某些特殊的功能之前,最好除了检测hasFeature()之外,还同时使用能力检测
文档写入
write()
接受一个字符串参数,即要写入到输出流中的文本
会原样写入
如果在文档加载结束后再调用document.write(),那么输出的内容将会重写整个页面
writeln()
接受一个字符串参数,即要写入到输出流中的文本
会在字符串的末尾添加一个换行符\n
open()
打开网页的输出流
close()
关闭网页的输出流
Element类型
用于表现XML或HTML元素,提供了对元素标签名、子节点及特性的访问
特征
nodeType的值为1
nodeName的值为元素的标签名
nodeValue的值为null
parentNode可能是Document或Element
其子节点可能是Element、Text、Comment、ProcessingInstruction、CDATASection或EntityReference
nodeName属性
访问元素的标签名
tagName属性
访问元素的标签名
HTML元素
所有HTML元素都由HTMLElement类型表示
HTMLElement类型直接继承自Element并添加了一些属性
id:元素在文档中的唯一标识符
title:有关元素的附加说明信息,一般通过工具提示条显示出来
lang:元素内容的语言代码,很少使用
dir:语言的方向,值为ltr(left-to-right,从左至右)或rtl(right-to-left,从右至左)
className:与元素的class特性对应,即为元素指定的CSS类
特性
getAttribute()
通过getAttribute()方法也可以取得自定义特性的值
根据HTML5规范,自定义特性应该加上data-前缀以便验证
特性(attribute)的名称是不区分大小写的
只有公认的(非自定义的)特性才会以属性的形式添加到DOM对象中
setAttribute()
接受两个参数:要设置的特性名和值
如果特性已经存在,setAttribute()会以指定的值替换现有的值;如果特性不存在,setAttribute()则创建该属性并设置相应的值
通过setAttribute()方法既可以操作HTML特性也可以操作自定义特性。通过这个方法设置的特性名会被统一转换为小写形式
removeAttribute()
用于彻底删除元素的特性
调用这个方法不仅会清除特性的值,而且也会从元素中完全删除特性
attribute属性
Element类型是使用attributes属性的唯一一个DOM节点类型
attrubutes属性中包含一个NamedNodeMap,与NodeList类似,也是一个动态的集合
元素的每一个特性都由一个Attr节点表示,每个节点都保存在NamedNodeMap对象中
NamedNodeMap对象的方法
getNamedItem(name):返回nodeName属性等于name的节点
removeNamedItem(name):从列表中移除nodeName属性等于name的节点
返回表示被删除特性的Attr节点
setNamedItem(node):向列表中添加节点,以节点的nodeName属性为索引
item(pos):返回位于数字pos位置处的节点
创建元素
document.createElement()方法
只接受一个参数,即要创建元素的标签名
这个标签名在HTML文档中不区分大小写,而在XML文档中,则是区分大小写的
创建新元素的同时,也为新元素设置了ownerDocument属性
一旦将元素添加到文档树中,浏览器就会立刻呈现该元素
元素的子节点
childNodes属性
包含了元素的所有子节点,这些子节点可能是元素、文本节点、注释或处理指令
Text类型
文本节点由Text类型表示,包含的是可以照字面解释的纯文本内容。纯文本中可以包含转义后的HTML字符,但不能包含HTML代码
特征
nodeType的值为3
nodeName的值为#text
nodeValue的值为节点所包含的文本
parentNode是一个Element
不支持子节点
可以通过nodeValue属性或data属性访问Text节点中包含的文本
操作节点中的文本
appendData(text):将text添加到节点的末尾
deleteData(offset, count):从offset指定的位置开始删除count个字符
insertData(offset, text):在offset指定的位置插入text
replaceData(offset, count, text):用text替换从offset指定的位置开始到offset+count为止处的文本
splitText(offset):从offset指定的位置将当前文本节点分成两个文本节点
substringData(offset, count):提取从offset指定的位置开始到offset+count为止处的字符串
length属性
保存着节点中字符的数目
在修改文本节点时,字符串会经过HTML(或XML)编码。也就是,小于号、大于号或引号都会像下面一样被转义
创建文本节点
createTextNode()方法
接受一个参数:要插入节点中的文本
作为参数的文本也将按照HTML或XML的格式进行编码
创建新文本节点的同时,也会为其设置ownerDocument属性
如果两个文本节点是相邻的同胞节点,那么这两个节点中的文本就会连起来显示,中间不会有空格
规范化文本节点
normalize()方法
将相邻文本节点合并
如果在一个包含两个或多个文本节点的父元素上调用normalize()方法,则会将所有文本节点合并成一个节点,结果节点的nodeValue等于将合并前每个文本节点的nodeValue值拼接起来的值
分割文本节点
splitText()方法
这个方法将一个文本节点分成两个文本节点,即按照指定的位置分割nodeValue值
原来的文本节点将包含从开始带指定位置之前的内容,新文本节点将包含剩下的文本。这个方法将会返回一个新文本节点,该节点与原节点的parentNode相同
Comment类型
注释在DOM中是通过Comment类型来表示的
特征
nodeType的值为8
nodeName的值为#comment
nodeValue的值是注释的内容
parentNode可能是Document或Element
不支持子节点
Comment类型与Text类型继承自相同的基类,因此它拥有除splitText()之外的所有字符串操作方法
使用createComment()方法可以创建注释节点
CDATASection类型
CDATASection类型只针对基于XML的文档,表示的是CDATA区域
特征
nodeType的值为4
nodeName的值为#cdata-section
nodeValue的值是CDATA区域中的内容
parentNode可能是Document或Element
不支持子节点
CDATASection类型继承自Text类型,因此拥有除splitText()之外的所有字符串操作方法
在真正的XML文档中,可以使用document.createCDataSection()来创建CDATA区域
DocumentType类型
DocumentType包含着与文档的doctype有关的所有信息
特征
nodeType的值为10
nodeName的值为doctype的名称
nodeValue的值为null
parentNode是Document
不支持子节点
在DOM1级中,DocumentType对象不能动态创建,只能通过解析文档代码的方式来创建
DOM1级描述了DocumentType对象的3个属性
name
表示文档类型的名称
保存着文档类型的名称,也就是出现在<!DOCTYPE之后的文本
entities
由文档类型描述的实体的NamedNodeMap对象
notations
由文档类型描述的符号的NamedNodeMap对象
DocumentFragment类型
在所有节点类型中,只有DocumentFragment在文档中没有对应的标记
DOM规定文档片段(document fragment)是一种轻量级的文档,可以包含和控制节点,但不会像完整的文档那样占用额外的资源
特征
nodeType的值为11
nodeName的值为#document-fragment
nodeValue的值为null
parentNode的值为null
子节点可以是Element、ProcessInstruction、Comment、Text、CDATASection或EntityReference
虽然不能把文档片段直接添加到文档中,但可以将它作为一个仓库来使用,即可以在里面保存将来可能会添加到文档中的节点
要创建文档片段,可以使用document.createDocumentFragment()方法
文档片段本身永远不会成为文档树的一部分
Attr类型
元素的特性在DOM中以Attr类型来表示
特征
nodeType的值为11
nodeName的值是特性的名称
nodeValue的值是特性的值
parentNode的值为null
在HTML中不支持子节点
在XML中子节点可以是Text或EntityReference
尽管它们也是节点,但特性却不被认为是DOM文档树的一部分。开发人员一般很少直接引用特性节点
Attr对象有3个属性
name
特性名称(与nodeName的值相同)
value
特性的值(与nodeValue的值相同)
specified
是一个布尔值,用于区别特性是在代码中指定的,还是默认的
DOM操作技术
动态脚本
向页面中插入JavaScript代码
通过<script>元素src特性包含外部文件
用<script>元素本身来包含代码
创建动态脚本
插入外部文件
直接插入JavaScript代码
动态样式
把CSS样式包含到HTML页面中
<link>元素用于包含来自外部的文件
<style>元素用于指定嵌入的样式
动态样式是在页面加载完成后动态添加到页面中的
操作表格
<table>元素的属性和方法
caption:保存着对<caption>元素的指针
tBodies:是一个<tbody>元素的HTMLCollection
tFoot:保存着对<tfoot>元素的指针
tHead:保存着对<thead>元素的指针
rows:是一个表格中所有行的HTMLCollection
createTHead():创建<thead>元素,将其放到表格中,返回引用
createTFoot():创建<tfoot>元素,将其放到表格中,返回引用
createCaption():创建<caption>元素,将其放到表格中,返回引用
deleteTHead():删除<thead>元素
deleteTFoot():删除<tfoot>元素
deleteCaption():删除<caption>元素
deleteRow(pos):删除指定位置的行
insertRow(pos):向rows集合中的指定位置插入一行
<tbody>元素的属性和方法
rows:保存着<tbody>元素中行的HTMLCollection
deleteRow(pos):删除指定位置的行
insertRow(pos):向rows集合中的位置插入一行,返回对新插入行的引用
<tr>元素的属性和方法
cells:保存着<tr>元素中单元格的HTMLCollection
deleteCell(pos):删除指定位置的单元格
insertCell(pos):向cells集合中的指定位置插入一个单元格,返回对新插入单元格的引用
使用NodeList
NodeList、NamedNodeMap和HTMLCollection这三个集合都是动态的,每当文档结构发生变化时,它们都会得到更新
从本质上说,所有NodeList对象都是在访问DOM文档时实时运行的查询
一般来说,应该尽量减少访问NodeList的次数,因为每次访问NodeList,都会运行一次基于文档查询。所以可以考虑将从NodeList中取得的值缓存起来