JavaScript 通过 Document 类型表示文档。

document 对象是 HTMLDocument(继承自 Document 类型)的一个实例,表示整个 HTML 页面。而且 document 对象是 window 对象的一个属性,因此可以将其作为全局对象来访问。

1. 特征

  • nodeType:9

  • nodeName:#document

  • nodeValue:null

  • parentNode:null

  • ownerDocument:null

2. 文档的子节点

DOM 标准中规定,Document 节点的子节点可以是 DocumentType、Element、ProcessingInstruction 或 Comment,但是还有两个内置的快捷访问其子节点的方式。

(1)documentElement
该属性始终指向 HTML 页面中的 html 元素

  1. var html = document.documentElement;

(2)通过子节点访问文档元素

  1. //=> 不兼容
  2. var html = document.firstChild;
  3. var html = document.childNodes[0];

作为 HTMLDocument 的实例,document 对象还有一个 body 属性,直接指向 body 元素。

  1. var body = document.body;

Document 类型的另一个可能的子节点是 DocumentType。 通常将 <!DOCTYPE> 标签当作一个与文档其他实体不同的实体,可以通过 doctype 属性来访问其信息。

  1. var doctype = document.doctype;

浏览器对 document.doctype 的支持差别很大:

  • IE8 及以前版本,会错误将其解释为一个注释节点, document.doctype 值始终为 null

  • IE9+ 及 FireFox,会将其作为文档的第一个子节点

  • Safari、Chrome 及 Opera,不作为文档的子节点,不会出现在 document.childNodes

从技术上讲,出现在 html 元素外部的注释应该算是文档的子节点。但是不同的浏览器存在很大差异。

  1. <!-- 第一条注释 -->
  2. <html>
  3. </html>
  4. <!-- 第二条注释 -->
  • IE8 及之前版本、Safari 3.1 及其更高版本、Opera、Chrome 只为第一条注释创建节点,不为第二条注释创建节点。结果,第一天注释成为文档中的第一个子节点

  • IE9+ 会将两条注释都创建节点

  • Firefox、Safari 3.1 及其以前版本,会忽略这两条注释

3. 文档信息

作为 HTMLDocument 的实例,document 对象还有一些标准的 Document 类型没有的属性,提供了 document 对象所表现的网页的一些信息

title 属性,包含着 title 元素中的文本。通过这个属性可以取得页面中的标题,也可以修改当前页面的标题并反映到浏览器的标题栏中。注意的是,修改 title 属性的值不会改变 title 元素

  1. var orginalTitle = document.title;
  2. document.title = 'new page title'

URL 属性包含页面中完整的 URL 地址

  1. var url = document.URL;

domain 属性值包含页面的域名

  1. var domain = document.domain;

referrer 属性保存着链接到当前页面的那个页面的 URL,在没有来源页面的情况下,referrer 属性可能会包含空字符串

  1. var referrer = document.referrer;

这三个关于网页请求的只有 domain 是可以设置的,但是由于安全方面的限制,也并非可以给 domain 设置任何值。如果 URL 中包含一个子域名,如:p2p.wrox.com,那么只能将 domain 设置为 wrox.com。不能将这个属性设置为 URL 中不包含的域。

  1. //=> 假设页面来自于 p2p.wrox.com
  2. document.domain = 'wrox.com'; //=> 成功
  3. document.domain = 'nczonline.net'; //=> 出错

由于跨域安全的限制,来自不同子域的页面无法通过 JavaScript 通信。而通过将每个页面的 document.domain 设置为相同的值,这些页面就可以互相访问对方包含的 JavaScript 对象了。

浏览器对 domain 属性还有一个限制,如果域名一开始是松散的(loose),那么不能将它再设置为紧绷的(tight)。即

  1. //=> 假设页面来自于 p2p.wrox.com
  2. document.domain = 'wrox.com'; //=> 松散的,成功
  3. document.domain = 'p2p.wrox.com'; //=> 紧绷的,出错

4. 查找元素

取得元素的操作可以使用 document 对象的几个方法来完成。

其中,有:getElementByIdgetElementsByTagNamegetElementsByNamegetElementsByClassName 这几个方法

对于 getElementById,必须与页面元素的 id 特性严格匹配,包括大小写。如果页面中有多个元素的 ID 相同,只返回文档中第一次出现的元素。

其中 IE7及低版本还有个有意思的怪癖:name 属性与给定 ID 匹配的表单元素也会被该方法返回。

对于 getElementsByTagNamegetElementsByNamegetElementsByClassName 这三个方法,都会返回一个 HTMLCollection 对象。

HTMLCollection 对象是一个动态集合,与 NodeList 对象类似,可以通过方括号或 item() 访问其中的项。

HTMLCollection 对象还有一个 namedItem 方法,使用这个方法可以通过元素的 name 属性来取得集合中的特定项。

  1. // 对于 <img name="myImage"></img>
  2. var myImage = image.namedItem('myImage');

同样支持直接按 name 属性来访问,这就为我们取得实际想要的元素提供便利。

  1. var myImage = image['myImage'];

对 HTMLCollection 而言,我们向方括号中传入数值或字符串的索引值,在后台,对数值索引就会调用 item() 方法,而对字符串索引就会调用 namedItem() 方法

5. 特殊的集合

这些集合都是 HTMLCollection 对象,为访问文档常用的部分提供快捷方式,包括:

  • document.anchors:包含文档中所有带 name 属性的 a 标签

  • document.applets:已不再使用

  • document.images:包含文档中的所有 img 标签

  • document.forms:包含文档中所有的 form 标签

  • document.links:包含文档中所有带 href 属性的 a 标签

6. DOM 一致性的检测

可以通过 document.implementtetion.hasFeature() 检测 DOM 功能的名称和版本号。

但是,检测并不一定准确,因为实现者可以自行决定是否与 DOM 规范的不同部分保持一致。返回 true 不意味着实现与规范一样。

所以最好还是进行能力检测。

7. 文档写入

document 对象有将输出流写入到网页中的能力。这个能力体现在四个方法中:write()writeln()open()close()。一般不需要使用。

其中 write()writeln() 方法都接受一个字符串参数,即要写入输出流中的文本,write 会原样写入,而 writeln 会在字符串末尾添加一个换行符。在页面被加载的过程中,可以使用这两个方法向页面中动态加入内容。这两个方法都会重写整个页面

方法 open()close() 分别用于打开和关闭网页的输出流,如果在页面加载期间使用前两个方法,则不需要用到这连个方法。