这次总结的是剩下的这些DOM类型节点,可能你见过却不经常使用但是了解一下总是好的,可以加深对DOM体系的整体理解~。本篇要介绍的是Comment,CDATASection,DocumentType,DocumentFragment,Attr类型。

Comment类型

原型链继承关系为comment实例.__proto__->Comment.prototype->CharacterData.prototype->Node.prototype->EventTarget.prototype->Object.prototype。

与Text节点类似,也可以通过nodeValue或data访问注释的内容。

var com=document.createComment('I am comment');
com;// <!--I am comment-->
com.data;// "I am comment"
com.nodeValue;// "I am comment"

注释在DOM中通过Comment类型来表示的,Comment节点具有以下特征:

  • nodeType值为8
  • nodeName值为"#comment"
  • nodeValue值是注释内容
  • parentNode可能为Document或Element
  • 没有子节点

1.使用document.createComment()并为其传递注释文本可创建注释节点。createComment继承自Document.prototype。

2.浏览器对于注释节点的处理有些差距
(1).当注释位于HTML元素外 :Chrome,<=IE9处理HTML元素之前的注释节点,FF和>IE9 处理之外的所有节点。

<!--I am first comment-->
<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body>
</body>
</html>
<!--I am last comment-->

Chrome46.0.2490.80:只处理出现在HTML元素之前的的注释节点,忽略出现在HTML元素之后的注释节点。

FF44.0.2:出现在HTML元素之前之后的注释节点都会处理。

>IE9:出现在HTML元素之前之后的注释节点都会处理。

<=IE9:只处理HTML元素之前的注释节点。 

注意:IE8中注释节点和文档声明被当作标签名为"!"的元素,开启IE8仿真模式后,由于IE8不支持访问DOM中一些API原生对象,所以通过使用getElementsByTagName()(继承自Document.prototype)可以取得被当作元素节点的注释节点和文档声明节点。


IE9没有把注释和文档声明当成元素节点,但却将文档声明节点<!Doctype html>视作注释节点。本图测试于IE9仿真

(2).当注释位于HTML元素内

<!DOCTYPE html>
<html>
<head>
<title></title>
<!-- I am comment-->
</head>
<body>
<!-- I am comment too-->
</body>
</html>

三大浏览器均能解释成注释节点。

CDATASection类型

  • 了解XHTML

说起CDATASection类型节点,就先说起XHTML(可扩展超文本标记语言),它是将HTML作为XML的应用而重新定义的一个标准,编写XHTML代码的规则要比HTML严格很多,比如

  1. XHTML元素必须被正确嵌套
  2. XHTML元素必须被正确关闭,即使是空标签也必须被正确关闭比如<br />,<img />,注意/与元素之间留有空格保证XHTML文档与当今浏览器兼容
  3. 标签名必须用小写字母
  4. XHTML文档必须拥有根元素
  5. 属性值必须加引号
  6. 属性不能简写
  7. 用id属性代替name属性,如<a />,<img />等
  8. XHTML DTD定义了强制使用的HTML元素
  9. 所有XHTML文档必须进行文档类型声明。

以下面代码块为例,它们在HTML中是有效的,但是在XHTML中是无效的

<script type="text/javascript">
function compare(a, b){
if(a < b){
console.log("A is less than B");
}else if(a > b){
console.log("A is greater than B");
}else{
console.log("A is equal to B");
}
}
</script>

在HTML中有特殊规则用以确定<script>元素中哪些内容可以被解析,但这些规则在XHTML中不适用。这里比较语句a < b的小于号在XHTML中将被当作开始一个新标签来解析,但作为标签来说小于号后面又不能跟空格,因此就会导致语法错误如下“不合法的元素名”,所以JS代码后面就解析不了原样显示在页面上。

即使将代码中a < b间的空格去掉变为a<b,也会提示出错“解析属性出错”,毕竟b后面跟的是“)”。

避免出现这种情况的解决方式有两种:
(1).应用相应的HTML实体(&lt;),替换代码中所有的小于号(<),替换后一切正常

(2).用一个CData片段来包含JS代码,因为在XHTML(XML)中CData片段是文档中一个特殊区域,这个区域可以包含不需要解析的任意格式的文本内容。很明显CDATA被解析为了一个节点。

<script type="text/javascript"><![CDATA[
function compare(a, b){
if(a < b){
console.log("A is less than B");
}esle if(a > b){
console.log("A is greater than B");
}else{
console.log("A is equal to B");
}
}
]]></script>


在兼容XHTML的浏览器中这个办法可行,但实际上还有不少浏览器不兼容XHTML因而不支持CData片段。这种情况下使用JS注释将CData标记注释掉就可。

<script type="text/javascript">
//<![[
function compare(a, b){
if(a < b){ }else if(a >b){ }else{ }
}
//]]>
</script>
  • CDATASection类型

用JS也可以创建CData片段:

CDATASection只针对基于XML的文档,表示的是CDATA区域,原型链的继承关系为CDATASection实例.__proto__=>CDATASection.prototype=>Text.prototype=>CharacterData.prototype=>Node.protoype=>EventTarget.prototype。

CDATASection节点具有下列特征:

  • nodeType值为4
  • nodeName值为"cdata-section"
  • nodeValue值是内容区域的内容
  • parentNode可能是Document或Element
  • 不支持子节点

(1).兼容性:CDATA区域只会出现在XML/XHTML文档中,对于HTML文档会把CDATA区域错误地解析为注释节点或过滤掉,>=IE10和FF和Chrome会解析为Comment类型节点。<IE10会忽略该节点,因为IE9之前的版本中不支持CDATASection类型。

(2).在真正XML文档中,可以使用document.createCDATASection(text)创建CDATA区域,只需传入节点内容即可。在HTML文档上使用document.createCDATASection()会报错说不支持HTML文档。CDATA节点不能插入document节点中,只能插进标签中。

var cd=document.createCDATASection('mycdata');
cd;// <![CDATA[mycdata]]>
document.appendChild(cd);/*Uncaught DOMException: Failed to execute 'appendChild' on 'Node':
Nodes of type '#cdata-section' may not be inserted inside nodes of type '#document'.*/

CDATA区段不能进行嵌套,CDATA区段包含了不会被解析器解析的文本,CDATA中的标签不会被视为标签同时实体也不会被展开,主要目的是为了包含注入XML片段之类的材料,无需转义所有分隔符。

DocumentType类型

DocumentType节点包含着与文档的doctype有关的信息,原型链继承关系为document.doctype.__proto__=>DocumentType.prototype=>Node.prototype=>EventTarget.prototype。

它具有下列特征:

  • nodeType值为10
  • nodeName值为doctype名称,保存文档类型的名称即当前文档最外层标签顶级元素,document.doctype.name也可获取,就是出现在<!DOCTYPE 之后的文本(不包括后面那些PUBLIC...DTD版本号和文件路径)获取的为小写内容(不论之前代码中是否大小写)。这两种方式都是不可写的,因为nodeName和name的访问器属性set为undefiend。

注:有点疑问,经测试document.doctype只能在HTML文档中获取到DocumentType节点,在XML/XHTML中均为null(表明document.doctype是一个空指针)。

  • nodeValue值为null
  • parentNode是Document
  • 没有子节点

在DOM1级中,DocumentType对象不能动态创建,只能通过解析文档代码的方式创建,支持它的浏览器会把DocumentType对象保存在document.doctype中。DOM1级描述了DocumentType对象的三个属性:name,entities,notations(它们都是DocumentType.prototype对象上的三个属性,但Chrome中好像已经没有后两个属性了,反正没获取到这两个属性)。

DocumentFragment类型

在所有节点类型中,只有DocumentFragment在文档中没有对应标记。原型链关系为: 文档片段实例.__proto__=>DocumentFragment.prototype=>Node.prototype=>EventTarget.prototype

注意文档片段类型只支持getElementById获取元素,没有getElementsByTagName那系列的,不过可以通过querySelector获取,毕竟很万能~
DOM规定文档片段是一种轻量级的文档,可以包含和控制节点,但不会像完整的文档那样占用额外的资源。DocumentFragment节点具有下列特征:

  • nodeType值为11
  • nodeName值为"#document-fragment"
  • nodeValue值为null
  • parentNode值为null
  • 子节点可以是Element,ProcessingInstruction,Comment,Text,CDATASection,EntityReference

可以把文档片段当作一个仓库来使用,可以在里面保存将来可能会添加到文档中的节点。创建文档片段使用document.createDocumentFragment()方法。
如果将文档中本身存在的节点添加到文档片段中,就会从文档树中移除该节点。


可以通过appendChild或insertBefore将文档片段中内容添加到文档中(其实还是继承自Node.prototype那些方法),在将文档片段作为参数传递给这两个方法时,实际上只会将文档片段的所有子节点添加到相应位置,文档片段节点本身永远不会成为文档树的一部分。假设想为ul元素添加三个列表项,如果逐个地添加列表项,将会导致浏览器反复渲染新信息。我们可以将所有列表项加到文档片段中,最后再一次性将它们添加到文档中。

var df = document.createDocumentFragment();
var ul= document.createElement('ul');
var li=null;
for(var i=0;i<3;i++){
li = document.createElement('li');
li.appendChild(document.createTextNode("Item"+(i+1)));
df.appendChild(li);
}
ul.appendChild(df);

现在看ul和df元素,说明文档片段节点并没加到ul中去,而是它里面的内容加进去了。

Attr类型

元素的特性在DOM中以Attr类型来表示,在除了<=IE7之外的所有浏览器都可以访问Attr类型的构造函数和原型。特性节点就是一种对象,就是存在于元素的attributes属性(继承自Element.prototype)中的节点。某元素的attributes属性指向的是一个NamedNodeMap类型的实例集合。在该集合中的每一项才是我们需要的属性节点对象。

原型链继承关系为:attrNode.__proto__=>Attr.prototype=>Node.prototype=>EventTarget.prototype

特性节点具有下列特征

  • nodeType值为2
  • nodename值是特性的名称
  • nodeValue值是特性的值
  • parentNode值为null
  • 在HTML中不支持子节点
  • 在XML中子节点可以是Text或EntityReference

尽管特性节点也是节点,但却不认为是DOM文档树中的一部分。开发人员最常使用的是getAttribute(),setAttribute(),removeAttribute()很少直接引用特性节点(这些方法继承自Element.prototype)。
(1).Attr对象有三个属性:name,value,specified
name :特性名称,与nodeName值相同
value :特性的值,与nodevalue值相同
specified :是一个布尔值,用以区别特性是在代码中指定的还是默认的

(2).创建新的特性节点:document.createAttribute()


当在调用createAttribute()时已经为name属性赋了值,所以后面就不需要给它赋值,在将特性节点添加到元素中时必须使用setAttributeNode。添加后可以通过attributes,getAttributeNode,getAttribute方法访问。不过不建议直接访问特性节点,使用getAttribute,setAttribute,removeAttribute比操作特性节点方便多。

参考

《JavaScript高级程序设计》

从原型链看DOM--Comment,CDATASection,DocumentType,DocumentFragment,Attr类型的更多相关文章

  1. 从原型链看DOM--Node类型

    前言: 本系列从原型,原型链,属性类型等方面下手学习了DOM文档对象模型,旨在弄清我们在DOM中常用的每一个属性和方法都清楚它从哪里来要到哪里做什么事,这样对于理解代码有一定启发.全靠自己在总结中摸索 ...

  2. 从原型链看DOM--Document类型

    JavaScript通过Document类型表示文档,原型链的继承关系为:document.__proto__->HTMLDocument.prototype->Document.prot ...

  3. 从原型链看DOM--Element类型

    Element类型用于表现XML或HTML元素,提供对元素标签名,子节点及特性的访问.原型链的继承关系为 某节点元素.__proto__->(HTML某元素Element.prototype)- ...

  4. 从原型链看DOM--Text类型

    文本节点由Text类型表示,包含的是可以按照字面解释的纯文本内容,纯文本中可以包含转义后的HTML字符但不能包含HTML代码.原型链继承关系为:textNode.__proto__->Text. ...

  5. [js]js原型链继承小结

    这是之前总结的, 发现有很多的毛病,就是重点不突出,重新翻看的时候还是得耗费很长时间去理解这玩意. js中的继承 js中什么是类 1,类是函数数据类型 2.每个类有一个自带prototype属性 pr ...

  6. js 原型链(转)

    1.1 理解原型链 JavaScript中几乎所有的东西都是对象,我们说数组是对象.DOM节点是对象.函数等也是对象,创建对象的Object也是对象(本身是构造函数),那么有一个重要的问题:对象从哪里 ...

  7. 【javascript基础】4、原型与原型链

    前言 荒废了好几天,在宿舍闷了几天了,一直想着回家放松,什么也没搞,论文就让老师催吧.不过,闲的没事干的感觉真是不好,还是看看书,写写博客吧,今天和大家说说函数的原型. 原型是什么 第一次看到这个的时 ...

  8. JavaScript面向对象(二)——成员属性、静态属性、原型属性与JS原型链

      前  言 JRedu 上一篇博客中,我们介绍了JS中的面向对象,并详细的解释了this的指向问题.本篇博客,我们继续来学习JS的面向对象.来深入理解一下JavaScript OOP中的成员属性/方 ...

  9. js javascript 原型链详解

    看了许多大神的博文,才少许明白了js 中原型链的概念,下面给大家浅谈一下,顺便也是为了巩固自己 首先看原型链之前先来了解一下new关键字的作用,在许多高级语言中,new是必不可少的关键字,其作用是为了 ...

随机推荐

  1. IE9 BUG overflow :auto 底部空白解决方案

    今天去升级了到IE9,运行项目的时候发现,我的div显示滚动条时候,用js动态加载进去的内容在光标移动的时候,底部自动被撑大留着空白, IE8 Chrome这些以前都试过 没发现这个问题 研究了好久 ...

  2. Differential Geometry之第七章曲面的若干整体性质

    1.曲面的整体描述 2.整体的Gauss-Bonnet公式 2.1.曲面的三角剖分 2.2.Gauss-Bonnet公式 = 2.3.Gauss-Bonnet定理的应用 2.3.1.切向量场的指数定理 ...

  3. 转载 Python导入模块的几种姿势

    作为一名新手Python程序员,你首先需要学习的内容之一就是如何导入模块或包.但是我注意到,那些许多年来不时使用Python的人并不是都知道Python的导入机制其实非常灵活.在本文中,我们将探讨以下 ...

  4. Yii2.0实现微信公众号后台开发

    接入微信 Yii2后台配置 1.在app/config/params.php中配置token参数 return [ //微信接入 'wechat' =>[ 'token' => 'your ...

  5. 【基础练习】【BFS+A*】codevs1225八数码难题题解

    题目描写叙述 Description Yours和zero在研究A*启示式算法.拿到一道经典的A*问题,可是他们不会做,请你帮他们. 问题描写叙述 在3×3的棋盘上,摆有八个棋子,每一个棋子上标有1至 ...

  6. Laravel5.1 搭建博客 --文章的增删改查

    教程源于:Laravel学院 继文件上传后呢,咱来搞一搞文章的事情. 1 更改数据表 我们需要改改数据表的结构 因为涉及到重命名列名 所以咱需要引入一个包:Doctrine: composer req ...

  7. iOS开发之--iOS APP打包的时候出现的四个选项

  8. Deep Learning的基本思想

    假设我们有一个系统S,它有n层(S1,…Sn),它的输入是I,输出是O,形象地表 示为: I =>S1=>S2=>…..=>Sn => O,如果输出O等于输入I,即输入I ...

  9. js修改剪切板内容的方法

    代码如下: //绑定在了body上,也可以绑定在其他可用元素行,但是不是所有元素都支持copy事件. $(document.body).bind({ copy: function(e) {//copy ...

  10. poj_1125 Floyd最短路

    题目大意 N个股票经纪人,每个股票经纪人都会将得到的消息传播给另外一些股票经纪人,传播的速度均不固定,且从A传到B的速度和B传到A的速度不一定相等.给定一个消息,并不一定能够传遍所有的股票经纪人,因为 ...