跳到主要内容

节点类型

从存在方式来看,文本节点总是包含在元素节点中,但不是每个元素节点都包含文本节点。 还有其它一些类型的节点,分别代表元素属性、 HTML 注释及其它一些与页面相关的信息。很多类型的节点都能够包含其它节点作为子节点。 每种节点类型都有一个关联的数值,保存在属性 nodeType 里。

节点类型1、2和3 最常用的节点。类型是1、2和3,也就是页面元素、它们的属性和包含的文本。

节点类型说明可包含的子节点的类型
1element元素
2Attr属性
3text文本(包括空白)
4CDATASectionCDATA 区域
5EntityReference实体引用
6Entity实体
7ProcessingInstruction执行指令
8CommentHTML 注释
9Document文档
10DocumentType文档类型( DTD )
11DocumentFragment文档片段
12Notation标签
nodeType 值nodeType节点类型
:--------------------:------------------------------------------------------:------------------------------------------------------------------
Document表示整个文档, DOM 树的根节点Element 、 processingInstruction 、 Comment 、 DocumentType
DocumentFragment文档片段,轻量级的 Document ,仅包含部分文档processingInstruction 、 Comment 、 Text 、 CDATASection 、 EntityReference
DocumentType为文档定义的实体提供接口
ProcessingInstruction表示处理命令
EntityReference表示实体引用元素ProcessingInstruction 、 Comment 、 Text 、 CDATASection 、 EntityReference
Element表示元素ProcessingInstruction 、 Comment 、 CDATASection 、 EntityReference
Attr表示属性Text 、 EntityReference
Text表示元素或属性的文本
CDATASection表示文档中的 CDATA 片段,还包含文本不会被解析器解析部分
Comment表示注释
Entity表示实体ProcessingInstruction 、 Comment 、 Text 、 CDATASection 、 EntityReference
Notation表示在 DTD 中声明的符号
function count(n) {
//定义统计函数
var num = 0;
if (n.nodeType == 1) num++;
// 检测是否是元素节点
var son = n.childNodes; // 获取所有的子节点
for (var i = 0; i < son.length; i++) {
num += count(son[i]);
}
return num;
}
alert('当前文档包含' + count(document) + '个元素');

childNodes 属性

每个节点都有一个 childNodes 属性。这个类似数组的属性包含了当前节点全部直接子节点的集合,可供用户访问这些子节点的信息。

childNodes 集合称为"节点列表"( NodeList ),其中的项目以数值进行索引。集合(在大多数情况下)的表现类似于数组。我们可以像访问数组元素一样访问集合里的项目,还可以像对待数组一样遍历集合的内容,但有些数组方法是不能用的,比如 push()和 pop()。

节点列表是一个动态集合,这表示集合的任何改变都会立即反映到列表。

小心空白当浏览器加载页面时, HTML 代码里的空白(比如空格和制表符)一般是被忽略的。但是,对于页面元素里存在的空白,比如有序列表

  • 里的空白,大多数浏览器都会创建文本类型的子节点( nodeType==3)。这样一来,仅使用 childNodes.length 未必能得到期望的结果
  • firstChild 和 lastChild
  • parentNode 父级节点
  • nextSibling 下一个兄弟节点,不存在则返回 null
  • previousSibling 上一个兄弟节点,不存在返回 null
  • nodeValue 返回保存在节点里的值,常用于返回文本节点里的内容
  • nodeName 以字符串形式返回节点的名称。这个属性是只读的,不能修改它的值

节点名称和值

使用节点的 nodeName 、 nodeValue 属性可以读取节点的名称和值。

节点类型nodeName 返回值nodeValue 返回值
Document#documentnull
DocumentFragment#document-fragmentnull
DocumentTypedoctype 名称null
EntityReference实体引用发名称null
Element元素的名称(标签名称)null
Attr属性的名称属性的值
ProcessingInstructiontarget节点的内容
Comment#comment注释的内容
Text#text节点的内容
CDATASection#cada-section节点的内容
Entity实体名称null
Notation符号名称null

节点的关系

节点之间的关系包括:上下级父子关系,相邻级别的兄弟关系。

  • 在节点树,最顶端节点为根节点
  • 除了根节点,每个节点都有一个父节点
  • 节点可以包括任何数量的子节点
  • 叶子没有字节点
  • 同级节点拥有同父节点

访问节点

  • ownerDocument 返回当前节点的根节点
  • parentNode 返回当前节点的父节点,所有的节点都仅有一个父节点
  • childNode 返回当前节点的所有子节点的节点列表
  • firstNode 返回当前节点的第一个子节点
  • lastNode 返回档期那节点的最后一个节点
  • nextNode 返回当前节点的下一个节点
  • previousSibling 返回当前节点之前的所有同级别的节点

childNodes

所有节点都有一个 childNodes 属性,该属性保存着一个 nodeList 对象,它包含所有子节点的列表。

<body>
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
</ul>
</body>
<script>
var tag = document.getElementsByTagName('ul')[0];
var a = tag.childNodes;
console.log(a[0].nodeType);
console.log(a.item(1).innerHTML);
console.log(a.length);
</script>

使用 Array.prototype.slice 方法可以把 nideList 转化为数字,这样就可以调用数组的方法。

var tag = document.getElementsByTagName('ul')[0];
var a = Array.prototype.slice.call(tag.childNodes, 0); // 把 nodeList 转换成数组
a.reverse();
console.log(a[0].nodeType); // 返回第一个节点类型,返回值 3 ,显示为文本节点
console.log(a[1].innerHTML); // 显示第二个节点所包含的文本
console.log(a.length); // 包含子节点个数。 nodeList 长度

文本节点和属性节点都不包含子节点,所以它们的 childNodes 属性永远返回一个空的 nodeList 。如果判断一个节点是否含有子节点,可以使用 hasChildNodes() 方法直接快速判断,或者使用 childNodes.length 值是否为 0 判断。

对于 IE 8 以前的版本,则需要另类方法。

function convertToArray(nodes) {
var array = null;
try {
array = Array.prototype.slice.call(nodes, 0);
// 非 IE 或者 IE 9+
} catch (ex) {
array = new Array();
for (var i = 0, len = nodes.length; i < len; i++) {
array.push(nodes[i]);
}
}
return array;
}

parentNode

每一个节点都有一个 parentNode 属性,该属性指向文档树中的父节点。包含在 childNodes 列表中的所有节点都具有的父节点,因此它们的 parentNode 的属性都指向同一个父节点。

parentNode 返回节点永远是一个元素节点,因为只有元素节点才可能包含子节点。不过, document 没有父节点, document 节点的 parentNode 属性将返回 null 。

ownerDocument

<!DOCTYPE html>
<html lang="en">
<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>
</head>
<body>
<span class="p c">span</span>
</body>
</html>

获取 body 元素:

var b = document.documentElement.lastChild;
var b = document.documentElement.firstChild.nextSibling.nextSibling;

可以这样获取 span 元素所包含的文本。

var text = document.documentElement.lastChild.firstChild.firstChild.nodeValue;

操作节点

methoden
appendChild()向节点的子节点列表的结尾添加新的子节点
cloneChild()复制节点
hasChildNodes()判断节点是否拥有子节点
insertBefore()在指定的子节点前添加新的子节点
normalize()合并相邻的 Text 节点并删除空的 Text 节点
removeChild()删除(并返回)当前节点的指定节点
replaceChild()用新节点替换旧节点"]

cloneNode() 用于克隆节点

node.cloneNode(include_all);

参数 include_all 是布尔值,如果是 true ,则将克隆节点,并复制所有的子节点;为 false 时,仅复制节点本身。复制后返回节点的副本属于文档所有,但并没有为它指定父节点,需要通过 appendChild()、 insertBefore()、 replaceChild() 方法将它添加到文档。

cloneNode() 方法不会复制添加到 DOM 节点的 JavaScript 属性,如事件处理程序。但是, IE 会复制事件处理程序!!!