Document 类型是 JavaScript 中表示文档节点的类型。在浏览器中,文档对象 document 是HTMLDocument 的实例(HTMLDocument 继承 Document),表示整个 HTML 页面。document 是 window对象的属性,因此是一个全局对象。Document 类型的节点有以下特征:
nodeName 值为"#document";
nodeValue 值为 null;
parentNode 值为 null;
ownerDocument 值为 null;
子节点可以是 DocumentType(最多一个)、Element(最多一个)、ProcessingInstruction或 Comment 类型。
Document 类型可以表示 HTML 页面或其他 XML 文档,但最常用的还是通过 HTMLDocument 的实例取得 document 对象。document 对象可用于获取关于页面的信息以及操纵其外观和底层结构。
文档子节点
虽然 DOM 规范规定 Document 节点的子节点可以是 DocumentType、Element、ProcessingInstruction 或 Comment,但也提供了两个访问子节点的快捷方式。第一个是 documentElement 属
性,始终指向 HTML 页面中的元素。虽然 document.childNodes 中始终有元素,但
使用 documentElement 属性可以更快更直接地访问该元素。假如有以下简单的页面:
浏览器解析完这个页面之后,文档只有一个子节点,即元素。这个元素既可以通过documentElement 属性获取,也可以通过 childNodes 列表访问,如下所示: ```let html = document.documentElement; // 取得对的引用 alert(html === document.childNodes[0]); // true alert(html === document.firstChild); // true ``` 这个例子表明 documentElement、firstChild 和 childNodes[0]都指向同一个值,即元素。 作为 HTMLDocument 的实例,document 对象还有一个 body 属性,直接指向元素。因为这个元素是开发者使用最多的元素,所以 JavaScript 代码中经常可以看到 document.body,比如: ```let body = document.body; // 取得对的引用 ``` 所有主流浏览器都支持 document.documentElement 和 document.body。 Document 类型另一种可能的子节点是 DocumentType。标签是文档中独立的部分,其信息可以通过 doctype 属性(在浏览器中是 document.doctype)来访问,比如: ```let doctype = document.doctype; // 取得对的引用 ``` 另外,严格来讲出现在元素外面的注释也是文档的子节点,它们的类型是 Comment。不过,由于浏览器实现不同,这些注释不一定能被识别,或者表现可能不一致。比如以下 HTML 页面: ```
``` 这个页面看起来有 3 个子节点:注释、元素、注释。逻辑上讲,document.childNodes应该包含 3 项,对应代码中的每个节点。但实际上,浏览器有可能以不同方式对待元素外部的 注释,比如忽略一个或两个注释。 一般来说,appendChild()、removeChild()和 replaceChild()方法不会用在 document 对象上。这是因为文档类型(如果存在)是只读的,而且只能有一个 Element 类型的子节点(即, 已经存在了)。① 文档信息 document 作为 HTMLDocument 的实例,还有一些标准 Document 对象上所没有的属性。这些属性提供浏览器所加载网页的信息。其中第一个属性是 title,包含
元素中的文本,通常显示在浏览器窗口或标签页的标题栏。通过这个属性可以读写页面的标题,修改后的标题也会反映在浏览器标题
栏上。不过,修改 title 属性并不会改变<title>元素。下面是一个例子:
```// 读取文档标题
let originalTitle = document.title;
// 修改文档标题
document.title = "New page title";
```
接下来要介绍的 3 个属性是 URL、domain 和 referrer。其中,URL 包含当前页面的完整 URL(地址栏中的 URL),domain 包含页面的域名,而 referrer 包含链接到当前页面的那个页面的 URL。如果当前页面没有来源,则 referrer 属性包含空字符串。所有这些信息都可以在请求的 HTTP 头部信息
中获取,只是在 JavaScript 中通过这几个属性暴露出来而已,如下面的例子所示:
```// 取得完整的 URL
let url = document.URL;
// 取得域名
let domain = document.domain;
// 取得来源
let referrer = document.referrer;
```
URL 跟域名是相关的。比如,如果 document.URL 是 http://www.wrox.com/WileyCDA/,则document.domain 就是 www.wrox.com。
在这些属性中,只有 domain 属性是可以设置的。出于安全考虑,给 domain 属性设置的值是有限——————————
① 元素是 HTMLHtmlElement 的实例,HTMLHtmlElement 继承 HTMLElement,HTMLElement 继承 Element,因此 HTML
文档可以包含子节点,但不能多于一个。
如果 URL包含子域名如 p2p.wrox.com,则可以将 domain 设置为"wrox.com"(URL包含“www”时也一样,比如 www.wrox.com)。不能给这个属性设置 URL 中不包含的值,比如:
```// 页面来自 p2p.wrox.com
document.domain = "wrox.com"; // 成功
document.domain = "nczonline.net"; // 出错!
```
当页面中包含来自某个不同子域的窗格()或内嵌窗格()时,设置document.domain 是有用的。因为跨源通信存在安全隐患,所以不同子域的页面间无法通过 JavaScript
通信。此时,在每个页面上把 document.domain 设置为相同的值,这些页面就可以访问对方的 JavaScript对象了。比如,一个加载自 www.wrox.com 的页面中包含一个内嵌窗格,其中的页面加载自
p2p.wrox.com。这两个页面的 document.domain 包含不同的字符串,内部和外部页面相互之间不能访问对方的 JavaScript 对象。如果每个页面都把 document.domain 设置为 wrox.com,那这两个页面之间就可以通信了。
浏览器对 domain 属性还有一个限制,即这个属性一旦放松就不能再收紧。比如,把document.domain 设置为"wrox.com"之后,就不能再将其设置回"p2p.wrox.com",后者会导致错误,比如:
```// 页面来自 p2p.wrox.com
document.domain = "wrox.com"; // 放松,成功
document.domain = "p2p.wrox.com"; // 收紧,错误!
```