• DOM可以将任何HMLT或XML文档描绘成一个由多层节点构成的结构,节点氛围几种不同的类型,每种类型分别表示文档中不同的信息及标记,每个节点都拥有各自的特点、数据和方法。
  • Node类型

DOM1级定义了一个Node接口,该接口将由DOM中的所以节点类型实现,除了IE之外,其他浏览器都可以访问到这个类型,js中的所有节点类型都继承自Node类型。

每个节点都有一个nodeType属性,用于表明节点的类型,下面12个数值常来表示类型:

  1. Node.ELEMENT_NODE(1);
  2. Node.ATTRIBUTE_NODE(2);
  3. Node.TEXT_NODE(2);
  4. Node.CDATA_SECTION_NODE(4);
  5. Node.ENTITY_REFERENCE_NODE(5);
  6. Node.ENTITY_NODE(6);
  7. Node.PROCESSING_INSTRUCTION_NODE(7)
  8. Node.COMMENT_NODE(8)
  9. Node.DOCUMENT_NODE(9)
  10. Node.DOCUMENT_TYPE_NODE(10)
  11. Node.DOCUMENTY_FRAGMENT_NODE(11)
  12. Node.NOTATION_NODE(12)

通过比较上面这些常量,可以很容易地确定节点的类型,例如:

If(someNode.nodeType==Node.ELEMENT_NODE){//在ie中无效

     alert(“Node is an element”);

}

由于ie没有公开Node类型的构造函数,因此上面的代码在ie中会导致错误,为了确保跨浏览器兼容,最好还是将nodeType属性和数字进行比较,如下:

 if(someNode.nodeType==1){

       alert(“Node is an element.”);

}

要了解节点的具体信息,可以使用nodeName和nodeValue这两个属性,这两个属性的值完全取决于节点的类型,在使用这两个值以前,最后是像下面这样先检测一下节点的类型。

if(someNode.nodeType==1){

  value=someNode.nodeName;

}
  • 节点关系

每个节点都有一个childNodes属性,其中保存着一个NodeList对象,NodeList是一种类数组对象,用于保存一组有序的节点,可以通过位置来访问这些节点。虽然可以通过方括号语法来方位NodeList的值,而且这个对象也有length属性,但它并不是Array的实例。NodeList对象的独特之处在于,它实际上是基于DOM结构动态执行查询的结果,因此DOM结构的变化能够自动反应在NodeList对象中。

下面例子展示了如何访问保存在NodeList中的节点,可以通过方括号,也可以使用item方法。

var firstChild=someNode.childNodes[0];

var secondChild=someNode.childNodes.item(1);

var count=someNode.chilNodes.length;

对arguments对象使用Array.prototype.slice()方法可以将其转换为数组,而采用同样方法,也可以将NodeList对象转换为数组,如下:

var arrayOfNodes=Array.prororype.slice.call(someNode.childNodes,0)’

除IE8及更早版本之外,这行代码能在任何浏览器中运行,由于IE8及更早版本将NodeList实现为一个COM对象,而我们不能像使用Jscript对象那样使用这种对象,因此上面的代码会导致错误,要想在ie中将NodeList转换为数组,必须手动枚举所有成员。如下:

function convertToArray(nodes){

  var array=null;

  try{

    array=Array.prororype.slice.call(nodes,0);

}catch(ex){

  Array=new Array();

  for(var i=0,len=nodes.length;i<len;i++){

    array.push(nodes[i]);

}

}

return array;

}

每个节点都有一个parentNode属性,该属性指向文档树中的父节点,包含在childNodes列表中的所有节点都具有相同的父节点,因此它们的parentNode属性都指向同一个节点。此外,包含在childNodes列表中的每个节点相互之间都是同胞节点,通过使用列表中每个节点的previousSibling和nextSibling属性,可以访问同一列表中的其他节点,列表中的第一个节点的previousSibling属性为null,而列表中最后一个节点的nextSibling属性的值同样为null,如下:

if(someNode.nextSibling===null){

  alert(“Last node in the parent’s childNodes list.”);

}else if(someNode.previousSibling===null){

  alert(“First node in the parent’s  childNodes list.”);

}

父节点的firstChild和lastChild属性分别指向其childNodes列表中的第一个和最后一个节点,其中,someNode.firstChild的值始终等于someNode.childNodes[0],而someNode.lastChild的值始终等于someNode.childNodes[someNode.childNodes.length-1]。在只有一个节点的情况下,firstChild和lastChild指向同一个节点,如果没有子节点,那么firstChild和lastChild的值均为null。

所有节点都有的最后一个属性是ownerDocument,该属性指向表示整个文档的文档节点,这种关系表示的是任何节点都属于它所在的文档,任何节点都不能同时存在于亮哥或更多个文档中,通过这个属性,我肯可以不必再节点层次中通过层层回溯到达顶端,而是可以直接访问文档节点。

DOM提供了一些操作节点的方法,其中,最常用的方法是appendChild,用于向childNodes列表的末尾添加一个节点,添加节点后,childNodes的新增节点、父节点及以前的最后一个子节点的关系指针都会相应得到更新,更新完成后,appendChild返回新增的节点,如下:

var returnedNode=someNode.appendChild(newNode);

alert(returnedNode==newNode);               //true

alert(someNode.lastChild==newNode);          //true

如果传入到appendChild中的节点已经是文档的一部分,那结果就是将该节点从原来的位置转移到新位置,如下:

var returnedNode=someNode.appendChild(someNode.firstChild);

alert(returnedNode==someNode.firstChild);   //false

alert(returnedNode==someNode.lastChild);   //true

如果需要把节点放在childNodes列表中某个特定的位置上,而不是放在末尾,那么可以使用insertBefore方法,这个方法接受两个参数:要插入的节点和作为参照的节点,插入节点后,被插入的节点会变成参照节点的前一个同胞节点,同时被方法返回。如下例子:

returnedNode=someNode.insertBefore(newNode,null);

alert(newNode==someNode.lastChild);          //true

var returnedNode=someNode.inserBefore(newNode,someNode.firstChild);

alert(retrunedNode==newNode);              //true

alert(newNode==someNode.firstChild);         //true

returnedNode=someNode.insertBefore(newNode,someNode.lastChild);

alert(newNode==someNode.chlidNodes[someNode.childNodes.length-2]);            //true

replaceChild方法接受的两个参数是:要插入的节点和要替换的节点。要替换的节点将由这个方法返回并从文档树中被移除,同时由要插入的节点占据其位置,如下:

var returnedNode=someNode.replaceChild(newNode,someNode.firstChild);

returnedNode=someNode.replaceChild(newNode,someNode.lastChild);

使用replaceChild插入一个节点时,该节点的所有关系指针都会从被它替换的节点复制过来。

removeChild方法移除节点。这个方法移除的节点仍然为文档所有,只不过在文档中已经没有了自己的位置。

cloneNode方法用于创建调用这个方法的节点的一个完全相同的副本,cloneNode方法接受一个布尔值参数,表示是否执行深复制,在参数为true的情况下,执行深复制,也就是在复制节点及其整个子节点树,在参数为false的情况下,执行浅复制,即只复制节点本身,复制后返回的节点副本属于文档所有。

  • Document类型

Js通过Document类型表示文档,在浏览器中,document对象是HTMLDocument的一个实例,表示整个html页面。而且,document对象是window对象的一个属性,Document节点具有下列特性:

  1. nodeTye的值为9;
  2. nodeName的值为“#document”;
  3. nodeValue的值为null;
  4. parentNode的值为null;
  5. ownerDocument的值为null;
  6. 其子节点可能是一个DocumentType(最多一个)、Element(最多一个)、ProcessingInstruction或Coment。

Document类型可以表示HTML页面或者其他基于XML的文档,不过,最常见的应用还是作为HTMLDocument实例的document对象,通过整个文档对象,不仅可以取得与页面的有关信息,而且还能操作页面的外观及其底层结构。

  • 文档的子节点

虽然DOM标准规定Document节点子节点可以是DocumentType、Element、ProcessingInstructior或Comment,但还有两个内置的访问其子节点的快捷键,第一个就是documentElement属性,该属性始终指向HTML页面中的<html>元素。另一个就是通过childNodes列表返回文档元素,但通过documentElement属性则更快捷,更直接的访问该元素。

作为HTMLDocument的实例,document对象还有一个body属性,直接指向body元素,因为开发人员经常要使用这个元素,所以document.body在js代码中出现的频率非常高,如下:

var body=document.body;

所有浏览器都支持document.documentElement和document.body属性。

Document另一个可能的子节点时DocumentType,通常将<!DOCTYPE>标签看成一个与文档其他部分不同的实体,可以通过doctype属性来访问它的信息。

var doctype=document.doctype;

浏览器对document.doctype的支持差别很大,总结如下:

  1. IE8之前版本:如果存在文档类型声明,会将其错误地理解为一个注释并把它当作Comment节点;而document.doctype的值始终未null。
  2. IE9+及Firefox:如果存在文档类型声明,则将其作为文档的第一个子节点;document.doctype是一个DocumentType节点,也可以通过document.firstChild或document.childNodes[0]访问同一个节点。
  3. Safari、Chrome和Opera:如果存在文档类型声明,则将其解析,但不作为文档子节点,document.doctype是一个DocumentType节点,但该节点不会出现在document.childNodes中。

如下:

<!--第一条注释 -->

<html>

   <body>

   </body>

</html>

<!—-第二条注释-->

看起来这个页面应该有3个节点:注释、html元素、注释。现实中浏览器在处理位于html外部的注释方面存在如下差异:

  1. IE8之前版本、Safari 3.1及更高版本、Opera和Chrome职位第一条注释创建节点,不为第二天注释创建节点,结果,第一条注释就会成为document.childNodes中的第一个子节点
  2. IE9及更高版本会将第一条注释创建为document.childNodes中的一个注释节点,也会将第二条注释创建为document.childNodes中的注释子节点。
  3. Firefox以及Safari 3.1之前的版本会完全忽略这个两条注释。

DOM(一)的更多相关文章

  1. 关于DOM的操作以及性能优化问题-重绘重排

     写在前面: 大家都知道DOM的操作很昂贵. 然后贵在什么地方呢? 一.访问DOM元素 二.修改DOM引起的重绘重排 一.访问DOM 像书上的比喻:把DOM和JavaScript(这里指ECMScri ...

  2. 读书笔记:JavaScript DOM 编程艺术(第二版)

    读完还是能学到很多的基础知识,这里记录下,方便回顾与及时查阅. 内容也有自己的一些补充. JavaScript DOM 编程艺术(第二版) 1.JavaScript简史 JavaScript由Nets ...

  3. 页面嵌入dom与被嵌入iframe的攻防

    1.情景一:自己的页面被引入(嵌入)至别人的页面iframe中 if(window.self != window.top){ //url是自己页面的url window.top.location.hr ...

  4. 通俗易懂的来讲讲DOM

    DOM是所有前端开发每天打交道的东西,但是随着jQuery等库的出现,大大简化了DOM操作,导致大家慢慢的“遗忘”了它的本来面貌.不过,要想深入学习前端知识,对DOM的了解是不可或缺的,所以本文力图系 ...

  5. HTML DOM 介绍

    本篇主要介绍DOM内容.DOM 节点.节点属性以及获取HTML元素的方法. 目录 1. 介绍 DOM:介绍DOM,以及对DOM分类和功能的说明. 2. DOM 节点:介绍DOM节点分类和节点层次. 3 ...

  6. HTML DOM 对象

    本篇主要介绍HTML DOM 对象:Document.Element.Attr.Event等4个对象. 目录 1. Document 对象:表示文档树的根节点,大部分属性和方法都是对元素进行操作. 2 ...

  7. 重撸js_2_基础dom操作

    1.node 方法 返回 含义 nodeName String 获取节点名称 nodeType Number 获取节点类型 nodeValue String 节点的值(注意:文本也是节点) 2.inn ...

  8. 虚拟dom与diff算法 分析

    好文集合: 深入浅出React(四):虚拟DOM Diff算法解析 全面理解虚拟DOM,实现虚拟DOM

  9. 窥探Vue.js 2.0 - Virtual DOM到底是个什么鬼?

    引言 你可能听说在Vue.js 2.0已经发布,并且在其中新添加如了一些新功能.其中一个功能就是"Virtual DOM". Virtual DOM是什么 在之前,React和Em ...

  10. jQuery学习之路(2)-DOM操作

    ▓▓▓▓▓▓ 大致介绍 jQuery作为JavaScript库,继承并发扬了JavaScript对DOM对象操作的特性,使开发人员能方便的操作DOM对象. ▓▓▓▓▓▓ jQuery中的DOM操作 看 ...

随机推荐

  1. input range样式优化

    首先HTML代码: <input id="snrPollInterval" type="range" min="1" max=&quo ...

  2. python安装pbkdf2 遇到错误TypeError: __call__() takes exactly 2 arguments (1 given)

    python安装模块时遇到如下错误, import packaging.requirements File "/usr/lib/python2.7/site-packages/packagi ...

  3. matlab练习程序(马尔可夫聚类MCL)

    本文主要参考: https://wenku.baidu.com/view/b7907665caaedd3383c4d31b.html https://blog.csdn.net/u010376788/ ...

  4. HtmlAgilityPack 的东西

    之前都是用正则抓取页面,本人正则不咋地,有些东西用抓取来很费劲,呵呵 在网上看到别人推荐一个 HtmlAgilityPack 的东西,网上找了资料,自己写了个抓取网页的例子,框架用的ASP.NET M ...

  5. Cannot obtain the required interface ("IID_IDBCreateCommand") from OLE DB provider "OraOLEDB.Oracle" for linked server xxxx

      今天遇到了一个关于LINKED SERVER查询报错的案例,链接服务器链接ORACLE数据库,测试没有错误,但是执行脚本的时候,报如下错误: Msg 7399, Level 16, State 1 ...

  6. iOS图片存在本地、再从本地获取图片

    图片存在本地.再从本地获取图片 //将图片保存到本地 + (void)SaveImageToLocal:(UIImage*)image Keys:(NSString*)key {     NSUser ...

  7. NPOI 笔记

    前言 文档:http://npoi.codeplex.com/documentation 示例:https://npoi.svn.codeplex.com/svn/ 下载:https://www.nu ...

  8. python3中list列表的一些操作

    最近遇到许多List的操作,感觉它是一种很重要的一种基础数据结构,本人掌握的也不是很扎实,这里找了一些列表的操作,常用函数,记录下来,希望对大家有用.如果理解有偏差,欢迎指正,感谢! (1)列表的合并 ...

  9. wamp 中安装cakephp Fatal error: You must enable the intl extension to use CakePHP. in XXX

    今天在wamp下安装cakephp3.x的时候,报出这么一条错误:Fatal error: You must enable the intl extension to use CakePHP. in ...

  10. 南邮ctf-web的writeup

    WEB 签到题 nctf{flag_admiaanaaaaaaaaaaa} ctrl+u或右键查看源代码即可.在CTF比赛中,代码注释.页面隐藏元素.超链接指向的其他页面.HTTP响应头部都可能隐藏f ...