前端温习(二): Javascriput 核心对象 Document 对象
- 陈大剩
- 2023-01-30 12:10:43
- 781
Document 对象
当浏览器载入 HTML
文档, 它就会成为 Document
对象。
Document
对象是 HTML
文档的根节点。
Document
对象使我们可以从脚本中对 HTML
页面中的所有元素进行访问。
在 HTML DOM (Document Object Model) 中 , 每一个元素都是 节点:
- 文档是一个文档节点
- 所有的
HTML
元素都是元素节点 - 所有
HTML
属性都是属性节点 - 文本插入到
HTML
元素是文本节点。are text nodes - 注释是注释节点
Document不同获取办法
- 对于正常的网页,直接使用
document
或window.document
- 对于
iframe
载入的网页,使用iframe
节点的contentDocument
属性 - 对
Ajax
操作返回的文档,使用XMLHttpRequest
对象的responseXML
属性 - 对于某个节点包含的文档,使用该节点的
ownerDocument
属性。
提示:
Document
对象是Window
对象的一部分,可通过window.document
属性对其进行访问。
Document 对象属性和方法
属性
属性 | 说明 |
---|---|
document.activeElement | 返回当前获取焦点元素 |
document.anchors | 返回对文档中所有 Anchor 对象的引用 |
document.baseURI | 返回文档的绝对基础 URI |
document.body | 返回文档的body元素 |
document.cookie | 设置或返回与当前文档有关的所有 cookie |
document.doctype | 返回与文档相关的文档类型声明 (DTD) |
document.documentElement | 返回文档的根节点 |
document.domain | 返回当前文档的域名 |
document.referrer | 返回载入当前文档的文档的 URL |
document.links | 返回对文档中所有 Area 和 Link 对象引用 |
document.title | 返回当前文档的标题 |
document.scripts | 返回页面中所有脚本的集合 |
… | … |
方法
方法 | 说明 |
---|---|
document.write() | 向文档写 HTML 表达式 或 JavaScript 代码 |
document.writeln() | 等同于 write() 方法,不同的是在每个表达式之后写一个换行符 |
document.adoptNode(node) | 从另外一个文档返回 adapded 节点到当前文档 |
document.addEventListener() | 向文档添加句柄 |
document.open() | 打开一个流,以收集来自任何 document.write() 或 document.writeln() 方法的输出 |
document.close() | 关闭用 document.open() 方法打开的输出流,并显示选定的数据 |
document.createAttribute() | 创建一个属性节点 |
document.createComment() | createComment() 方法可创建注释节点 |
document.createDocumentFragment() | 创建空的 DocumentFragment 对象,并返回此对象 |
document.createElement() | 创建元素节点 |
document.createTextNode() | 创建文本节点 |
document.getElementsByClassName() | 返回文档中所有指定类名的元素集合,作为 NodeList 对象 |
document.getElementById() | 返回对拥有指定 id 的第一个对象的引用 |
document.getElementsByName() | 返回带有指定名称的对象集合 |
document.getElementsByTagName() | 返回带有指定标签名的对象集合 |
document.importNode() | 把一个节点从另一个文档复制到该文档以便应用 |
document.normalize() | 删除空文本节点,并连接相邻节点 |
document.normalizeDocument() | 删除空文本节点,并连接相邻节点的 |
document.querySelector() | 返回文档中匹配指定的CSS选择器的第一元素 |
document.querySelectorAll() | document.querySelectorAll() 是 HTML5中引入的新方法,返回文档中匹配的CSS选择器的所有元素节点列表 |
document.removeEventListener() | 移除文档中的事件句柄(由 addEventListener() 方法添加) |
document.renameNode() | 重命名元素或者属性节点 |
… | … |
使用
由于属性和方法比较多,就把一些常用的一些属性和方法展开说明。
属性
doctype
对于HTML
文档来说,document
对象一般有两个子节点。第一个子节点是document.doctype
,它是一个对象,包含了当前文档类型(Document Type Declaration,简写DTD)信息。对于HTML5
文档,该节点就代表<!DOCTYPE html>
。如果网页没有声明 DTD,该属性返回null
。// document.firstChild 通常就返回这个节点 var doctype = document.doctype; doctype // "<!DOCTYPE html>" doctype.name // "html"
documentElement
document.documentElement
属性,表示当前文档的根节点(root)。它通常是document
节点的第二个子节点,紧跟在document.doctype
节点后面。
对于HTML
网页,该属性返回HTML
节点,代表<html lang="en">
。defaultView
defaultView
属性,在浏览器中返回document
对象所在的window
对象,否则返回null
。body
body
属性返回当前文档的body
或frameset
节点,如果不存在这样的节点,就返回null
。这个属性是可写的,如果对其写入一个新的节点,会导致原有的所有子节点被移除。
head
head
属性返回当前文档的head
节点。如果当前文档有多个head
,则返回第一个。activeElement
activeElement
属性返回当前文档中获得焦点的那个元素。用户通常可以使用tab
键移动焦点,使用空格键激活焦点,比如如果焦点在一个链接上,此时按一下空格键,就会跳转到该链接。documentURI、URL
documentURI
属性和URL
属性都返回当前文档的网址。不同之处是documentURI
属性是所有文档都具备的,URL
属性则是HTML
文档独有的。domain
domain
属性返回当前文档的域名。比如,某张网页的网址是http://www.example.com/hello.html
,domain
属性就等于www.example.com
。如果无法获取域名,该属性返回null
。// 如果当前域名等于指定域名,则关闭窗口。 var badDomain = "www.example.xxx"; if (document.domain === badDomain) window.close();
二级域名的情况下,
domain
属性可以设置为对应的一级域名。比如,当前域名是sub.example.com
,则domain
属性可以设置为example.com
。除此之外的写入,都是不可以的。lastModified
lastModified
属性返回当前文档最后修改的时间戳,格式为字符串。document.lastModified // '08/05/2021 17:34:49' if (Date.parse(doc1.lastModified) Date.parse(doc2.lastModified)) { // ... }
注意,
lastModified
属性的值是字符串,所以不能用来直接比较,两个文档谁的日期更新,需要用Date.parse
方法转成时间戳格式,才能进行比较。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 // "passed" // 跳转到另一个网址 document.location.assign('http://www.google.com') // 优先从服务器重新加载 document.location.reload(true) // 优先从本地缓存重新加载(默认值) document.location.reload(false) // 跳转到另一个网址,但当前文档不保留在history对象中, // 即无法用后退按钮,回到当前文档 document.location.assign('http://www.google.com') // 将location对象转为字符串,等价于document.location.href document.location.toString()
referrer
referrer
属性返回一个字符串,表示前文档的访问来源,如果是无法获取来源或是用户直接键入网址,而不是从其他网页点击,则返回一个空字符串。title
title
属性返回当前文档的标题,该属性是可写的。document.title = '新标题';
characterSet
characterSet
属性返回渲染当前文档的字符集,比如UTF-8
、ISO-8859-1
。readyState
readyState
属性返回当前文档的状态,共有三种可能的值,加载HTML
代码阶段(尚未完成解析)是“loading”,加载外部资源阶段是“interactive”,全部加载完成是“complete”。// 基本检查 if (document.readyState === 'complete') { // ... } // 轮询检查 var interval = setInterval(function() { if (document.readyState === 'complete') { clearInterval(interval); // ... } }, 100);
designModed
designMode
属性控制当前document
是否可编辑。通常会打开iframe
的designMode
属性,将其变为一个所见即所得的编辑器。iframe_node.contentDocument.designMode = "on";
implementation
implementation
属性返回一个对象,用来甄别当前环境部署了哪些DOM
相关接口。implementation
属性的hasFeature
方法,可以判断当前环境是否部署了特定版本的特定接口。// 当前环境部署了DOM HTML 2.0版和MutationEvents的2.0版。 document.implementation.hasFeature( 'HTML, 2.0 ') // true document.implementation.hasFeature('MutationEvents','2.0') // true
compatMode
compatMode
属性返回浏览器处理文档的模式,可能的值为BackCompat
(向后兼容模式)和CSS1Compat
(严格模式)。anchors,embeds,forms,images,links,scripts,styleSheets
这几个属性都是返回文档内部特定元素的集合。这些集合都是动态的,原节点有任何变化,立刻会反映在集合中anchors
返回网页中所有的a
节点元素【必须指定了 name属性的 a 元素】embeds
返回网页中所有嵌入对象【即embed标签】,返回的格式为类似数组的对象(nodeList)forms
返回页面中所有表单images
返回页面所有图片元素【即img标签】links
返回当前文档所有的链接元素【即a
标签,或者说具有href
属性的元素】scripts
返回当前文档的所有脚本【script标签】styleSheets
返回一个类似数组的对象,包含了当前网页的所有样式表
方法
open()
用于新建一个文档,供write
方法写入内容。它实际上等于清除当前文档,重新写入内容。不要将此方法与window.open()
混淆,后者用来打开一个新窗口,与当前文档无关。close
用于关闭open
方法所新建的文档。一旦关闭,write
方法就无法写入内容了。如果再调用write
方法,就等同于又调用open
方法,新建一个文档,再写入内容。write()
用于向当前文档写入内容。只要当前文档还没有用close
方法关闭,它所写入的内容就会追加在已有内容的后面。// 页面显示“helloworld” document.open(); document.write("hello"); document.write("world"); document.close();
如果页面已经渲染完成(
DOMContentLoaded
事件发生之后),再调用write
方法,它会先调用open
方法,擦除当前文档所有内容,然后再写入。document.addEventListener("DOMContentLoaded", function(event) { document.write('<p>Hello World!</p>'); }); // 等同于 document.addEventListener("DOMContentLoaded", function(event) { document.open(); document.write('<p>Hello World!</p>'); document.close(); });
如果在页面渲染过程中调用
write
方法,并不会调用open
方法。(可以理解成,open
方法已调用,但close
方法还未调用。)<html> <body> hello <script type="text/javascript"> document.write("world") </script> </body> </html>
注意:虽然调用close方法之后,无法再用write方法写入内容,但这时当前页面的其他DOM节点还是会继续加载。
// 还是会显示“hello world” <script type="text/javascript"> document.open(); document.write("hello"); document.close(); </script>
总之,除了某些特殊情况,应该尽量避免使用document.write这个方法
writeln()
document.writeln
方法与write
方法完全一致,除了会在输出内容的尾部添加换行符document.write(1); document.write(2); // 12 document.writeln(1); document.writeln(2); // 1 // 2 //
注意:writeln方法添加的是ASCII码的换行符,渲染成HTML网页时不起作用。
hasFocus()
返回一个布尔值,表示当前文档之中是否有元素被激活或获得焦点。focused = document.hasFocus();
注意:有焦点的文档必定被激活(active),反之不成立,激活的文档未必有焦点。比如如果用户点击按钮,从当前窗口跳出一个新窗口,该新窗口就是激活的,但是不拥有焦点。
querySelector()
返回匹配指定的CSS
选择器的元素节点。如果有多个节点满足匹配条件,则返回第一个匹配的节点。如果没有发现匹配的节点,则返回null
。var el1 = document.querySelector('.myclass'); var el2 = document.querySelector('#myParent > [ng-click]');
querySelector
方法无法选中CSS
伪元素**getElementById()**【非常常用的一个方法】
返回匹配指定ID
属性的元素节点。如果没有发现匹配的节点,则返回null
。var elem = document.getElementById("para1");
getElementById
方法与querySelector
方法都能获取元素节点,不同之处是querySelector
方法的参数使用CSS
选择器语法,getElementById
方法的参数是HTML
标签元素的id
属性。// 两个方法都能选中id为myElement的元素,但是getElementById()比querySelector()效率高得多 document.getElementById('myElement') document.querySelector('#myElement')
注意:在搜索匹配节点时,
id
属性是大小写敏感的。比如,如果某个节点的id
属性是main
,那么document.getElementById("Main")
将返回null
,而不是指定节点。querySelectorAll()
返回匹配指定的CSS
选择器的所有节点,返回的是NodeList
类型的对象。NodeList
对象不是动态集合,所以元素节点的变化无法实时反映在返回结果中。// 返回class属性是note或alert的div元素 elementList = document.querySelectorAll(selectors); // 逗号分隔的多个CSS选择器,返回所有匹配其中一个选择器的元素 var matches = document.querySelectorAll('div.note, div.alert'); // 支持复杂的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');
如果
querySelectorAll
方法和getElementsByTagName
方法的参数是字符串“*”,则会返回文档中的所有HTML
元素节点。与querySelector
方法一样,querySelectorAll
方法无法选中CSS
伪元素。**getElementsByClassName()**【非常常用的一个方法】
返回一个类似数组的对象(HTMLCollection类型的对象),包括了所有class
名字符合指定条件的元素(搜索范围包括本身),元素的变化实时反映在返回结果中。这个方法不仅可以在document
对象上调用,也可以在任何元素节点上调用。// document对象上调用 var elements = document.getElementsByClassName(names); // 非document对象上调用 var elements = rootElement.getElementsByClassName(names); // 参数可以是多个空格分隔的class名字,返回同时具有这些节点的元素。 // 选择同时具有red和test的元素 document.getElementsByClassName('red test');
**getElementsByTagName()**【非常常用的一个方法】
返回所有指定标签的元素(搜索范围包括本身)。返回值是一个HTMLCollection
对象,也就是说,搜索结果是一个动态集合,任何元素的变化都会实时反映在返回的集合中。这个方法不仅可以在document
对象上调用,也可以在任何元素节点上调用。// 返回当前文档的所有p元素节点 var paras = document.getElementsByTagName("p");
注意:getElementsByTagName方法会将参数转为小写后,再进行搜索
getElementsByName()
用于选择拥有name
属性的HTML
元素,比如form
、img
、frame
、embed
和object
,返回一个NodeList
格式的对象,不会实时反映元素的变化// 假定有一个表单是<form name="x"></form> var forms = document.getElementsByName("x"); forms[0].tagName // "FORM"
注意:在IE浏览器使用这个方法,会将没有
name
属性、但有同名 id 属性的元素也返回,所以name和id属性最好设为不一样的值。elementFromPoint()
返回位于页面指定位置的元素// 返回相对于当前窗口左上角的横坐标和纵坐标,单位是CSS像素 var element = document.elementFromPoint(x, y);
createElement()
用来生成HTML
元素节点var element = document.createElement(tagName); // 实例 var newDiv = document.createElement("div");
注意:
createElement
方法的参数为元素的标签名,即元素节点的tagName
属性。如果传入大写的标签名,会被转为小写。如果参数带有尖括号(即<和>)或者是null
,会报错。
createTextNode()
用来生成文本节点,参数为所要生成的文本节点的内容// 新建一个div节点和一个文本节点,文本节点插入div节点 var newDiv = document.createElement("div"); var newContent = document.createTextNode("Hello"); newDiv.appendChild(newContent);
createAttribute()
生成一个新的属性对象节点,并返回它。attribute = document.createAttribute(name); // createAttribute 方法的参数 name,是属性的名称 var node = document.getElementById("div1"); var a = document.createAttribute("my_attrib"); a.value = "newVal"; node.setAttributeNode(a); // 等同于 var node = document.getElementById("div1"); node.setAttribute("my_attrib", "newVal");
createDocumentFragment()
生成一个DocumentFragment
对象。DocumentFragment
对象是一个存在于内存的DOM
片段,但是不属于当前文档,常常用来生成较复杂的DOM
结构,然后插入当前文档。这样做的好处在于,因为DocumentFragment
不属于当前文档,对它的任何改动,都不会引发网页的重新渲染,比直接修改当前文档的DOM
有更好的性能表现。var docfrag = document.createDocumentFragment(); [1, 2, 3, 4].forEach(function(e) { var li = document.createElement("li"); li.textContent = e; docfrag.appendChild(li); }); document.body.appendChild(docfrag);
createEvent()
生成一个事件对象,该对象可以被element.dispatchEven
t 方法使用,触发指定事件// createEvent 方法的参数是事件类型,比如 UIEvents、MouseEvents、MutationEvents、HTMLEvents var event = document.createEvent('Event'); event.initEvent('build', true, true); document.addEventListener('build', function (e) { // ... }, false); document.dispatchEvent(event);
reateNodeIterator()
createNodeIterator
方法返回一个DOM
的子节点遍历器。var nodeIterator = document.createNodeIterator( document.body, NodeFilter.SHOW_ELEMENT );
上面代码返回
body
元素的遍历器。createNodeIterator
方法的第一个参数为遍历器的根节点,第二个参数为所要遍历的节点类型,这里指定为元素节点。其他类型还有所有节点(NodeFilter.SHOW_ALL)、文本节点(NodeFilter.SHOW_TEXT)、评论节点(NodeFilter.SHOW_COMMENT)等。所谓“遍历器”,在这里指可以用
nextNode
方法和previousNode
方法依次遍历根节点的所有子节点。var nodeIterator = document.createNodeIterator(document.body); var pars = []; var currentNode; while (currentNode = nodeIterator.nextNode()) { pars.push(currentNode); }
上面代码使用遍历器的
nextNode
方法,将根节点的所有子节点,按照从头部到尾部的顺序,读入一个数组。nextNode
方法先返回遍历器的内部指针所在的节点,然后会将指针移向下一个节点。所有成员遍历完成后,返回null
。previousNode
方法则是先将指针移向上一个节点,然后返回该节点。// currentNode和previousNode都指向同一个的节点 var nodeIterator = document.createNodeIterator( document.body, NodeFilter.SHOW_ELEMENT ); var currentNode = nodeIterator.nextNode(); var previousNode = nodeIterator.previousNode(); currentNode === previousNode // true
注意:遍历器返回的第一个节点,总是根节点
createTreeWalker()
返回一个DOM
的子树遍历器。它与createNodeIterator
方法的区别在于,后者只遍历子节点,而它遍历整个子树。// createTreeWalker 第一个参数,是所要遍历的根节点,第二个参数指定所要遍历的节点类型 // 遍历body节点下属的所有元素节点,将它们插入nodeList数组 var treeWalker = document.createTreeWalker( document.body, NodeFilter.SHOW_ELEMENT ); var nodeList = []; while(treeWalker.nextNode()) nodeList.push(treeWalker.currentNode);
adoptNode()
将某个节点,从其原来所在的文档移除,插入当前文档,并返回插入后的新节点。// importNode 方法从外部文档拷贝指定节点,插入当前文档 var node = document.importNode(externalNode, deep);
importNode()
用于创造一个外部节点的拷贝,然后插入当前文档。它的第一个参数是外部节点,第二个参数是一个布尔值,表示对外部节点是深拷贝还是浅拷贝,默认是浅拷贝(false)。虽然第二个参数是可选的,但是建议总是保留这个参数,并设为true。// 从iframe窗口,拷贝一个指定节点myNode,插入当前文档 var iframe = document.getElementsByTagName("iframe")[0]; var oldNode = iframe.contentWindow.document.getElementById("myNode"); var newNode = document.importNode(oldNode, true); document.getElementById("container").appendChild(newNode);
注意:
importNode
方法只是拷贝外部节点,这时该节点的父节点是null
。下一步还必须将这个节点插入当前文档的DOM
树。