概述
document
节点是文档的根节点,每张网页都有自己的document
节点。window.document
属性就指向这个节点。只要浏览器开始载入HTML文档,这个节点对象就存在了,可以直接调用。
document
节点有不同的办法可以获取。
- 对于正常的网页,直接使用
document
或window.document
。
- 对于
iframe
载入的网页,使用iframe
节点的contentDocument
属性。
- 对Ajax操作返回的文档,使用XMLHttpRequest对象的
responseXML
属性。
- 对于包含某个节点的文档,使用该节点的
ownerDocument
属性。
上面这四种document
节点,都部署了Document接口,因此有共同的属性和方法。当然,各自也有一些自己独特的属性和方法,比如HTML和XML文档的document
节点就不一样。
内部节点属性
document
节点有很多属性,其中相当一部分属于快捷方式,指向文档内部的某个节点。
document.doctype,document.documentElement,document.defaultView
对于HTML文档来说,document
对象一般有两个子节点。第一个子节点是document.doctype
,它是一个对象,包含了当前文档类型(Document Type Declaration,简写DTD)信息。对于HTML5文档,该节点就代表
。如果网页没有声明DTD,该属性返回null
。
var doctype = document.doctype;
doctype // ""
doctype.name // "html"
document.firstChild
通常就返回这个节点。
document.documentElement
属性返回当前文档的根节点(root)。它通常是document
节点的第二个子节点,紧跟在document.doctype
节点后面。对于HTML网页,该属性返回
节点。
document.defaultView
属性,在浏览器中返回document
对象所在的window
对象,否则返回null
。
document.defaultView === window // true
document.body,document.head
document.head
属性返回当前文档的
节点,document.body
属性返回当前文档的
。
document.head === document.querySelector('head') // true
document.body === document.querySelector('body') // true
这两个属性总是存在的,如果网页源码里面省略了
或
,浏览器会自动创造。另外,这两个属性是可写的,如果对其写入一个新的节点,会导致原有的所有子节点被移除。
document.activeElement
document.activeElement
属性返回当前文档中获得焦点的那个元素。用户通常可以使用Tab键移动焦点,使用空格键激活焦点。比如,如果焦点在一个链接上,此时按一下空格键,就会跳转到该链接。
节点集合属性
以下属性返回文档内部特定元素的集合,都是类似数组的对象。这些集合都是动态的,原节点有任何变化,立刻会反映在集合中。
document.links,document.forms,document.images,document.embeds
document.links
属性返回当前文档所有设定了href
属性的a
及area
元素。
document.forms
属性返回页面中所有表单元素form
。
var selectForm = document.forms[0];
上面代码获取文档第一个表单。
document.images
属性返回页面所有图片元素(即img
标签)。
var imglist = document.images;
for(var i = 0; i < imglist.length; i++) {
if (imglist[i].src === 'banner.gif') {
// ...
}
}
上面代码在所有img
标签中,寻找特定图片。
document.embeds
属性返回网页中所有嵌入对象,即embed
标签。
以上四个属性返回的都是HTMLCollection
对象实例。
document.links instanceof HTMLCollection // true
document.images instanceof HTMLCollection // true
document.forms instanceof HTMLCollection // true
document.embeds instanceof HTMLCollection // true
由于HTMLCollection
实例可以用HTML元素的id
或name
属性引用,因此如果一个元素有id
或name
属性,就可以在上面这四个属性上引用。
// HTML代码为
//
document.scripts,document.styleSheets
document.scripts
属性返回当前文档的所有脚本(即script
标签)。
var scripts = document.scripts;
if (scripts.length !== 0 ) {
console.log('当前网页有脚本');
}
document.scripts
返回的也是HTMLCollection
实例。
document.scripts instanceof HTMLCollection // true
因此,如果一个script
标签有id
或name
属性,就可以在document.scripts
上引用。
// HTML代码为
//
document.styleSheets
属性返回一个类似数组的对象,代表当前网页的所有样式表。每个样式表对象都有cssRules
属性,返回该样式表的所有CSS规则,这样这可以操作具体的CSS规则了。
var allSheets = [].slice.call(document.styleSheets);
上面代码中,使用slice
方法将document.styleSheets
转为数组,以便于进一步处理。
文档信息属性
以下属性返回文档信息。
document.documentURI,document.URL
document.documentURI
属性和document.URL
属性都返回一个字符串,表示当前文档的网址。不同之处是documentURI
属性可用于所有文档(包括 XML 文档),URL
属性只能用于 HTML 文档。
document.URL
// http://www.example.com/about
document.documentURI === document.URL
// true
如果文档的锚点(#anchor
)变化,这两个属性都会跟着变化。
document.domain
document.domain
属性返回当前文档的域名。比如,某张网页的网址是 http://www.example.com/hello.html ,domain
属性就等于[www.example.com](http://www.example.com/)
。如果无法获取域名,该属性返回null
。
var badDomain = 'www.example.xxx';
if (document.domain === badDomain)
window.close();
上面代码判断,如果当前域名等于指定域名,则关闭窗口。
二级域名的情况下,domain属性可以设置为对应的一级域名。比如,当前域名是sub.example.com,则domain属性可以设置为example.com。除此之外的写入,都是不可以的。
document.lastModified
document.lastModified
属性返回当前文档最后修改的时间戳,格式为字符串。
document.lastModified
// Tuesday, July 10, 2001 10:19:42
注意,lastModified
属性的值是字符串,所以不能用来直接比较,两个文档谁的日期更新,需要用Date.parse
方法转成时间戳格式,才能进行比较。
if (Date.parse(doc1.lastModified) > Date.parse(doc2.lastModified)) {
// ...
}
document.location
document.location
属性返回location
对象,提供了当前文档的URL信息。
// 当前网址为 http://user:passwd@www.example.com:4097/path/a.html?x=111#part1
document.location.href // "http://user:passwd@www.example.com:4097/path/a.html?x=111#part1"
document.location.protocol // "http:"
document.location.host // "www.example.com:4097"
document.location.hostname // "www.example.com"
document.location.port // "4097"
document.location.pathname // "/path/a.html"
document.location.search // "?x=111"
document.location.hash // "#part1"
document.location.user // "user"
document.location.password // "passwd"
location
对象有以下方法。
location.assign()
location.reload()
location.toString()
// 跳转到另一个网址
document.location.assign('http://www.google.com')
// 优先从服务器重新加载
document.location.reload(true)
// 优先从本地缓存重新加载(默认值)
document.location.reload(false)
// 跳转到新网址,并将取代掉history对象中的当前记录
document.location.replace('http://www.google.com');
// 将location对象转为字符串,等价于document.location.href
document.location.toString()
如果将新的网址赋值给location
对象,网页就会自动跳转到新网址。
document.location = 'http://www.example.com';
// 等同于
document.location.href = 'http://www.example.com';
也可以指定相对URL。
document.location = 'page2.html';
如果指定的是锚点,浏览器会自动滚动到锚点处。
document.location = '#top';
注意,采用上面的方法重置URL,跟用户点击链接跳转的效果是一样的。上一个网页依然将保存在浏览器历史之中,点击“后退”按钮就可以回到前一个网页。
如果不希望用户看到前一个网页,可以使用location.replace
方法,浏览器history
对象就会用新的网址,取代当前网址,这样的话,“后退”按钮就不会回到当前网页了。它的一个应用就是,当脚本发现当前是移动设备时,就立刻跳转到移动版网页。
document.location
属性与window.location
属性等价。
document.location === window.location // true
历史上,IE曾经不允许对document.location
赋值,为了保险起见,建议优先使用window.location
。如果只是单纯地获取当前网址,建议使用document.URL
,语义性更好。
document.referrer,document.title,document.characterSet
document.referrer
属性返回一个字符串,表示当前文档的访问来源,如果是无法获取来源或是用户直接键入网址,而不是从其他网页点击,则返回一个空字符串。
document.referrer
的值,总是与HTTP头信息的Referer
保持一致,但是它的拼写有两个r
。
document.title
属性返回当前文档的标题,该属性是可写的。
document.title = '新标题';
document.characterSet
属性返回渲染当前文档的字符集,比如UTF-8、ISO-8859-1。
document.readyState
document.readyState
属性返回当前文档的状态,共有三种可能的值。
-
loading
:加载HTML代码阶段(尚未完成解析)
-
interactive
:加载外部资源阶段时
-
complete
:加载完成时
这个属性变化的过程如下。
- 浏览器开始解析HTML文档,
document.readyState
属性等于loading
。
- 浏览器遇到HTML文档中的
元素,并且没有async
或defer
属性,就暂停解析,开始执行脚本,这时document.readyState
属性还是等于loading
。
- HTML文档解析完成,
document.readyState
属性变成interactive
。
- 浏览器等待图片、样式表、字体文件等外部资源加载完成,一旦全部加载完成,
document. readyState
属性变成complete
。
下面的代码用来检查网页是否加载成功。
// 基本检查
if (document.readyState === 'complete') {
// ...
}
// 轮询检查
var interval = setInterval(function() {
if (document.readyState === 'complete') {
clearInterval(interval);
// ...
}
}, 100);
document.designMode
document.designMode
属性控制当前文档是否可编辑,通常用在制作所见即所得编辑器。打开iframe
元素包含的文档的designMode
属性,就能将其变为一个所见即所得的编辑器。
document.implementation
document.implementation
属性返回一个对象,用来甄别当前环境部署了哪些DOM相关接口。implementation
属性的hasFeature
方法,可以判断当前环境是否部署了特定版本的特定接口。
document.implementation.hasFeature('HTML', '2.0')
// true
document.implementation.hasFeature('MutationEvents','2.0')
// true
上面代码表示,当前环境部署了DOM HTML 2.0版和MutationEvents的2.0版。
document.compatMode
compatMode
属性返回浏览器处理文档的模式,可能的值为BackCompat
(向后兼容模式)和CSS1Compat
(严格模式)。
一般来说,如果网页代码的第一行设置了明确的DOCTYPE
(比如
),document.compatMode
的值都为CSS1Compat
。
document.cookie
document.cookie
属性用来操作浏览器Cookie,详见《浏览器环境》一章的《Cookie》部分。
读写相关的方法
document.write(),document.writeln()
document.write
方法用于向当前文档写入内容。只要当前文档还没有用close
方法关闭,它所写入的内容就会追加在已有内容的后面。
// 页面显示“helloworld”
document.open();
document.write('hello');
document.write('world');
document.close();
注意,document.write
会当作HTML代码解析,不会转义。
document.write('hello world
');
如果页面已经解析完成(DOMContentLoaded
事件发生之后),再调用write
方法,它会先调用open
方法,擦除当前文档所有内容,然后再写入。
document.addEventListener('DOMContentLoaded', function (event) {
document.write('Hello World!
');
});
// 等同于
document.addEventListener('DOMContentLoaded', function (event) {
document.open();
document.write('Hello World!
');
document.close();
});
如果在页面渲染过程中调用write
方法,并不会调用open
方法。(可以理解成,open
方法已调用,但close
方法还未调用。)
hello
world
在浏览器打开上面网页,将会显示hello world
。
document.write
是JavaScript语言标准化之前就存在的方法,现在完全有更符合标准的方法向文档写入内容(比如对innerHTML
属性赋值)。所以,除了某些特殊情况,应该尽量避免使用document.write
这个方法。
document.writeln
方法与write
方法完全一致,除了会在输出内容的尾部添加换行符。
document.write(1);
document.write(2);
// 12
document.writeln(1);
document.writeln(2);
// 1
// 2
//
注意,writeln
方法添加的是ASCII码的换行符,渲染成HTML网页时不起作用,即在网页上显示不出换行。
查找节点的方法
以下方法用来查找某个节点。
document.querySelector(),document.querySelectorAll()
document.querySelector
方法接受一个CSS选择器作为参数,返回匹配该选择器的元素节点。如果有多个节点满足匹配条件,则返回第一个匹配的节点。如果没有发现匹配的节点,则返回null
。
var el1 = document.querySelector('.myclass');
var el2 = document.querySelector('#myParent > [ng-click]');
document.querySelectorAll
方法与querySelector
用法类似,区别是返回一个NodeList
对象,包含所有匹配给定选择器的节点。
elementList = document.querySelectorAll('.myclass');
这两个方法的参数,可以是逗号分隔的多个CSS选择器,返回匹配其中一个选择器的元素节点。
var matches = document.querySelectorAll('div.note, div.alert');
上面代码返回class
属性是note
或alert
的div
元素。
这两个方法都支持复杂的CSS选择器。
// 选中data-foo-bar属性等于someval的元素
document.querySelectorAll('[data-foo-bar="someval"]');
// 选中myForm表单中所有不通过验证的元素
document.querySelectorAll('#myForm :invalid');
// 选中div元素,那些class含ignore的除外
document.querySelectorAll('DIV:not(.ignore)');
// 同时选中div,a,script三类元素
document.querySelectorAll('DIV, A, SCRIPT');
但是,它们不支持CSS伪元素的选择器(比如:first-line
和:first-letter
)和伪类的选择器(比如:link
和:visited
),即无法选中伪元素和伪类。
如果querySelectorAll
方法的参数是字符串*
,则会返回文档中的所有HTML元素节点。另外,querySelectorAll
的返回结果不是动态集合,不会实时反映元素节点的变化。
最后,这两个方法除了定义在document
对象上,还定义在元素节点上,即在元素节点上也可以调用。
document.getElementsByTagName()
document.getElementsByTagName
方法返回所有指定HTML标签的元素,返回值是一个类似数组的HTMLCollection
对象,可以实时反映HTML文档的变化。如果没有任何匹配的元素,就返回一个空集。
var paras = document.getElementsByTagName('p');
paras instanceof HTMLCollection // true
上面代码返回当前文档的所有p
元素节点。
HTML标签名是大小写不敏感的,因此getElementsByTagName
方法也是大小写不敏感的。另外,返回结果中,各个成员的顺序就是它们在文档中出现的顺序。
如果传入*
,就可以返回文档中所有HTML元素。
var allElements = document.getElementsByTagName('*');
注意,HTML元素本身也定义了getElementsByTagName
方法,返回该元素的后代元素中符合指定标签的元素。也就是说,这个方法不仅可以在document
对象上调用,也可以在任何元素节点上调用。
var firstPara = document.getElementsByTagName('p')[0];
var spans = firstPara.getElementsByTagName('span');
上面代码选中第一个p
元素内部的所有span
元素。
document.getElementsByClassName()
document.getElementsByClassName
方法返回一个类似数组的对象(HTMLCollection
实例对象),包括了所有class
名字符合指定条件的元素,元素的变化实时反映在返回结果中。
var elements = document.getElementsByClassName(names);
由于class
是保留字,所以JavaScript一律使用className
表示CSS的class
。
如果参数是一个空格分隔的字符串,元素的class
必须符合所有字符串之中所有的class
才会返回。
var elements = document.getElementsByClassName('foo bar');
上面代码返回同时具有foo
和bar
两个class
的元素,foo
和bar
的顺序不重要。
注意,正常模式下,CSS的class
是大小写敏感的。(quirks mode
下,大小写不敏感。)
与getElementsByTagName
方法一样,getElementsByClassName
方法不仅可以在document
对象上调用,也可以在任何元素节点上调用。
// 非document对象上调用
var elements = rootElement.getElementsByClassName(names);
document.getElementsByName()
document.getElementsByName
方法用于选择拥有name
属性的HTML元素(比如
、
、![]()
、
、
和