W3Cschool
恭喜您成為首批注冊(cè)用戶
獲得88經(jīng)驗(yàn)值獎(jiǎng)勵(lì)
document
節(jié)點(diǎn)是文檔的根節(jié)點(diǎn),每張網(wǎng)頁(yè)都有自己的document
節(jié)點(diǎn)。window.document
屬性就指向這個(gè)節(jié)點(diǎn)。只要瀏覽器開始載入HTML文檔,這個(gè)節(jié)點(diǎn)對(duì)象就存在了,可以直接調(diào)用。
document
節(jié)點(diǎn)有不同的辦法可以獲取。
document
或window.document
。iframe
載入的網(wǎng)頁(yè),使用iframe
節(jié)點(diǎn)的contentDocument
屬性。responseXML
屬性。ownerDocument
屬性。上面這四種document
節(jié)點(diǎn),都部署了Document接口,因此有共同的屬性和方法。當(dāng)然,各自也有一些自己獨(dú)特的屬性和方法,比如HTML和XML文檔的document
節(jié)點(diǎn)就不一樣。
document
節(jié)點(diǎn)有很多屬性,其中相當(dāng)一部分屬于快捷方式,指向文檔內(nèi)部的某個(gè)節(jié)點(diǎn)。
對(duì)于HTML文檔來說,document
對(duì)象一般有兩個(gè)子節(jié)點(diǎn)。第一個(gè)子節(jié)點(diǎn)是document.doctype
,它是一個(gè)對(duì)象,包含了當(dāng)前文檔類型(Document Type Declaration,簡(jiǎn)寫DTD)信息。對(duì)于HTML5文檔,該節(jié)點(diǎn)就代表<!DOCTYPE html>
。如果網(wǎng)頁(yè)沒有聲明DTD,該屬性返回null
。
var doctype = document.doctype;
doctype // "<!DOCTYPE html>"
doctype.name // "html"
document.firstChild
通常就返回這個(gè)節(jié)點(diǎn)。
document.documentElement
屬性返回當(dāng)前文檔的根節(jié)點(diǎn)(root)。它通常是document
節(jié)點(diǎn)的第二個(gè)子節(jié)點(diǎn),緊跟在document.doctype
節(jié)點(diǎn)后面。對(duì)于HTML網(wǎng)頁(yè),該屬性返回<html>
節(jié)點(diǎn)。
document.defaultView
屬性,在瀏覽器中返回document
對(duì)象所在的window
對(duì)象,否則返回null
。
document.defaultView === window // true
document.head
屬性返回當(dāng)前文檔的<head>
節(jié)點(diǎn),document.body
屬性返回當(dāng)前文檔的<body>
。
document.head === document.querySelector('head') // true
document.body === document.querySelector('body') // true
這兩個(gè)屬性總是存在的,如果網(wǎng)頁(yè)源碼里面省略了<head>
或<body>
,瀏覽器會(huì)自動(dòng)創(chuàng)造。另外,這兩個(gè)屬性是可寫的,如果對(duì)其寫入一個(gè)新的節(jié)點(diǎn),會(huì)導(dǎo)致原有的所有子節(jié)點(diǎn)被移除。
document.activeElement
屬性返回當(dāng)前文檔中獲得焦點(diǎn)的那個(gè)元素。用戶通??梢允褂肨ab鍵移動(dòng)焦點(diǎn),使用空格鍵激活焦點(diǎn)。比如,如果焦點(diǎn)在一個(gè)鏈接上,此時(shí)按一下空格鍵,就會(huì)跳轉(zhuǎn)到該鏈接。
以下屬性返回文檔內(nèi)部特定元素的集合,都是類似數(shù)組的對(duì)象。這些集合都是動(dòng)態(tài)的,原節(jié)點(diǎn)有任何變化,立刻會(huì)反映在集合中。
document.links
屬性返回當(dāng)前文檔所有設(shè)定了href
屬性的a
及area
元素。
document.forms
屬性返回頁(yè)面中所有表單元素form
。
var selectForm = document.forms[0];
上面代碼獲取文檔第一個(gè)表單。
document.images
屬性返回頁(yè)面所有圖片元素(即img
標(biāo)簽)。
var imglist = document.images;
for(var i = 0; i < imglist.length; i++) {
if (imglist[i].src === 'banner.gif') {
// ...
}
}
上面代碼在所有img
標(biāo)簽中,尋找特定圖片。
document.embeds
屬性返回網(wǎng)頁(yè)中所有嵌入對(duì)象,即embed
標(biāo)簽。
以上四個(gè)屬性返回的都是HTMLCollection
對(duì)象實(shí)例。
document.links instanceof HTMLCollection // true
document.images instanceof HTMLCollection // true
document.forms instanceof HTMLCollection // true
document.embeds instanceof HTMLCollection // true
由于HTMLCollection
實(shí)例可以用HTML元素的id
或name
屬性引用,因此如果一個(gè)元素有id
或name
屬性,就可以在上面這四個(gè)屬性上引用。
// HTML代碼為
// <form name="myForm" >
document.myForm === document.forms.myForm // true
document.scripts
屬性返回當(dāng)前文檔的所有腳本(即script
標(biāo)簽)。
var scripts = document.scripts;
if (scripts.length !== 0 ) {
console.log('當(dāng)前網(wǎng)頁(yè)有腳本');
}
document.scripts
返回的也是HTMLCollection
實(shí)例。
document.scripts instanceof HTMLCollection // true
因此,如果一個(gè)script
標(biāo)簽有id
或name
屬性,就可以在document.scripts
上引用。
// HTML代碼為
// <script id="myScript" >
document.scripts.myScript
// <script id="myScript"></script>
document.styleSheets
屬性返回一個(gè)類似數(shù)組的對(duì)象,代表當(dāng)前網(wǎng)頁(yè)的所有樣式表。每個(gè)樣式表對(duì)象都有cssRules
屬性,返回該樣式表的所有CSS規(guī)則,這樣這可以操作具體的CSS規(guī)則了。
var allSheets = [].slice.call(document.styleSheets);
上面代碼中,使用slice
方法將document.styleSheets
轉(zhuǎn)為數(shù)組,以便于進(jìn)一步處理。
以下屬性返回文檔信息。
document.documentURI
屬性和document.URL
屬性都返回一個(gè)字符串,表示當(dāng)前文檔的網(wǎng)址。不同之處是documentURI
屬性是所有文檔都具備的,URL
屬性則是HTML文檔獨(dú)有的。
document.documentURI === document.URL
// true
另外,如果文檔的錨點(diǎn)(#anchor
)變化,這兩個(gè)屬性都不會(huì)跟著變化,它們的值是靜態(tài)的。但是,document.location
會(huì)跟著變化,document.location
總是返回最新的URL,會(huì)跟蹤錨點(diǎn)的變化。
document.domain
屬性返回當(dāng)前文檔的域名。比如,某張網(wǎng)頁(yè)的網(wǎng)址是 http://www.example.com/hello.html ,domain
屬性就等于www.example.com
。如果無法獲取域名,該屬性返回null
。
var badDomain = 'www.example.xxx';
if (document.domain === badDomain)
window.close();
上面代碼判斷,如果當(dāng)前域名等于指定域名,則關(guān)閉窗口。
二級(jí)域名的情況下,domain屬性可以設(shè)置為對(duì)應(yīng)的一級(jí)域名。比如,當(dāng)前域名是sub.example.com,則domain屬性可以設(shè)置為example.com。除此之外的寫入,都是不可以的。
document.lastModified
屬性返回當(dāng)前文檔最后修改的時(shí)間戳,格式為字符串。
document.lastModified
// Tuesday, July 10, 2001 10:19:42
注意,lastModified
屬性的值是字符串,所以不能用來直接比較,兩個(gè)文檔誰(shuí)的日期更新,需要用Date.parse
方法轉(zhuǎn)成時(shí)間戳格式,才能進(jìn)行比較。
if (Date.parse(doc1.lastModified) > Date.parse(doc2.lastModified)) {
// ...
}
document.location
屬性返回location
對(duì)象,提供了當(dāng)前文檔的URL信息。
// 當(dāng)前網(wǎng)址為 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"
location
對(duì)象有以下方法。
location.assign()
location.reload()
location.toString()
// 跳轉(zhuǎn)到另一個(gè)網(wǎng)址
document.location.assign('http://www.google.com')
// 優(yōu)先從服務(wù)器重新加載
document.location.reload(true)
// 優(yōu)先從本地緩存重新加載(默認(rèn)值)
document.location.reload(false)
// 跳轉(zhuǎn)到新網(wǎng)址,并將取代掉history對(duì)象中的當(dāng)前記錄
document.location.replace('http://www.google.com');
// 將location對(duì)象轉(zhuǎn)為字符串,等價(jià)于document.location.href
document.location.toString()
如果將新的網(wǎng)址賦值給location
對(duì)象,網(wǎng)頁(yè)就會(huì)自動(dòng)跳轉(zhuǎn)到新網(wǎng)址。
document.location = 'http://www.example.com';
// 等同于
document.location.href = 'http://www.example.com';
也可以指定相對(duì)URL。
document.location = 'page2.html';
如果指定的是錨點(diǎn),瀏覽器會(huì)自動(dòng)滾動(dòng)到錨點(diǎn)處。
document.location = '#top';
注意,采用上面的方法重置URL,跟用戶點(diǎn)擊鏈接跳轉(zhuǎn)的效果是一樣的。上一個(gè)網(wǎng)頁(yè)依然將保存在瀏覽器歷史之中,點(diǎn)擊“后退”按鈕就可以回到前一個(gè)網(wǎng)頁(yè)。
如果不希望用戶看到前一個(gè)網(wǎng)頁(yè),可以使用location.replace
方法,瀏覽器history
對(duì)象就會(huì)用新的網(wǎng)址,取代當(dāng)前網(wǎng)址,這樣的話,“后退”按鈕就不會(huì)回到當(dāng)前網(wǎng)頁(yè)了。它的一個(gè)應(yīng)用就是,當(dāng)腳本發(fā)現(xiàn)當(dāng)前是移動(dòng)設(shè)備時(shí),就立刻跳轉(zhuǎn)到移動(dòng)版網(wǎng)頁(yè)。
document.location
屬性與window.location
屬性等價(jià)。
document.location === window.location // true
歷史上,IE曾經(jīng)不允許對(duì)document.location
賦值,為了保險(xiǎn)起見,建議優(yōu)先使用window.location
。如果只是單純地獲取當(dāng)前網(wǎng)址,建議使用document.URL
,語(yǔ)義性更好。
document.referrer
屬性返回一個(gè)字符串,表示當(dāng)前文檔的訪問來源,如果是無法獲取來源或是用戶直接鍵入網(wǎng)址,而不是從其他網(wǎng)頁(yè)點(diǎn)擊,則返回一個(gè)空字符串。
document.referrer
的值,總是與HTTP頭信息的Referer
保持一致,但是它的拼寫有兩個(gè)r
。
document.title
屬性返回當(dāng)前文檔的標(biāo)題,該屬性是可寫的。
document.title = '新標(biāo)題';
document.characterSet
屬性返回渲染當(dāng)前文檔的字符集,比如UTF-8、ISO-8859-1。
document.readyState
屬性返回當(dāng)前文檔的狀態(tài),共有三種可能的值。
loading
:加載HTML代碼階段(尚未完成解析)interactive
:加載外部資源階段時(shí)complete
:加載完成時(shí)這個(gè)屬性變化的過程如下。
document.readyState
屬性等于loading
。<script>
元素,并且沒有async
或defer
屬性,就暫停解析,開始執(zhí)行腳本,這時(shí)document.readyState
屬性還是等于loading
。document.readyState
屬性變成interactive
。document. readyState
屬性變成complete
。下面的代碼用來檢查網(wǎng)頁(yè)是否加載成功。
// 基本檢查
if (document.readyState === 'complete') {
// ...
}
// 輪詢檢查
var interval = setInterval(function() {
if (document.readyState === 'complete') {
clearInterval(interval);
// ...
}
}, 100);
document.designMode
屬性控制當(dāng)前文檔是否可編輯,通常用在制作所見即所得編輯器。打開iframe
元素包含的文檔的designMode
屬性,就能將其變?yōu)橐粋€(gè)所見即所得的編輯器。
<iframe id="editor" src="about:blank"></iframe>
<script>
!(function () {
var editor = document.getElementById('editor');
editor.contentDocument.designMode = 'on';
})();
</script>
document.implementation
屬性返回一個(gè)對(duì)象,用來甄別當(dāng)前環(huán)境部署了哪些DOM相關(guān)接口。implementation
屬性的hasFeature
方法,可以判斷當(dāng)前環(huán)境是否部署了特定版本的特定接口。
document.implementation.hasFeature('HTML', '2.0')
// true
document.implementation.hasFeature('MutationEvents','2.0')
// true
上面代碼表示,當(dāng)前環(huán)境部署了DOM HTML 2.0版和MutationEvents的2.0版。
compatMode
屬性返回瀏覽器處理文檔的模式,可能的值為BackCompat
(向后兼容模式)和CSS1Compat
(嚴(yán)格模式)。
一般來說,如果網(wǎng)頁(yè)代碼的第一行設(shè)置了明確的DOCTYPE
(比如<!doctype html>
),document.compatMode
的值都為CSS1Compat
。
document.cookie
屬性用來操作瀏覽器Cookie,詳見《瀏覽器環(huán)境》一章的《Cookie》部分。
document.open
方法用于新建一個(gè)文檔,供write方法寫入內(nèi)容。它實(shí)際上等于清除當(dāng)前文檔,重新寫入內(nèi)容。不要將此方法與window.open()
混淆,后者用來打開一個(gè)新窗口,與當(dāng)前文檔無關(guān)。
document.close
方法用于關(guān)閉open
方法所新建的文檔。一旦關(guān)閉,write
方法就無法寫入內(nèi)容了。如果再調(diào)用write
方法,就等同于又調(diào)用open
方法,新建一個(gè)文檔,再寫入內(nèi)容。
document.write
方法用于向當(dāng)前文檔寫入內(nèi)容。只要當(dāng)前文檔還沒有用close
方法關(guān)閉,它所寫入的內(nèi)容就會(huì)追加在已有內(nèi)容的后面。
// 頁(yè)面顯示“helloworld”
document.open();
document.write('hello');
document.write('world');
document.close();
注意,document.write
會(huì)當(dāng)作HTML代碼解析,不會(huì)轉(zhuǎn)義。
document.write('<p>hello world</p>');
如果頁(yè)面已經(jīng)解析完成(DOMContentLoaded
事件發(fā)生之后),再調(diào)用write
方法,它會(huì)先調(diào)用open
方法,擦除當(dāng)前文檔所有內(nèi)容,然后再寫入。
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();
});
如果在頁(yè)面渲染過程中調(diào)用write
方法,并不會(huì)調(diào)用open
方法。(可以理解成,open
方法已調(diào)用,但close
方法還未調(diào)用。)
<html>
<body>
hello
<script type="text/javascript">
document.write("world")
</script>
</body>
</html>
在瀏覽器打開上面網(wǎng)頁(yè),將會(huì)顯示hello world
。
document.write
是JavaScript語(yǔ)言標(biāo)準(zhǔn)化之前就存在的方法,現(xiàn)在完全有更符合標(biāo)準(zhǔn)的方法向文檔寫入內(nèi)容(比如對(duì)innerHTML
屬性賦值)。所以,除了某些特殊情況,應(yīng)該盡量避免使用document.write
這個(gè)方法。
document.writeln
方法與write
方法完全一致,除了會(huì)在輸出內(nèi)容的尾部添加換行符。
document.write(1);
document.write(2);
// 12
document.writeln(1);
document.writeln(2);
// 1
// 2
//
注意,writeln
方法添加的是ASCII碼的換行符,渲染成HTML網(wǎng)頁(yè)時(shí)不起作用,即在網(wǎng)頁(yè)上顯示不出換行。
以下方法用來查找某個(gè)節(jié)點(diǎn)。
document.querySelector
方法接受一個(gè)CSS選擇器作為參數(shù),返回匹配該選擇器的元素節(jié)點(diǎn)。如果有多個(gè)節(jié)點(diǎn)滿足匹配條件,則返回第一個(gè)匹配的節(jié)點(diǎn)。如果沒有發(fā)現(xiàn)匹配的節(jié)點(diǎn),則返回null
。
var el1 = document.querySelector('.myclass');
var el2 = document.querySelector('#myParent > [ng-click]');
document.querySelectorAll
方法與querySelector
用法類似,區(qū)別是返回一個(gè)NodeList
對(duì)象,包含所有匹配給定選擇器的節(jié)點(diǎn)。
elementList = document.querySelectorAll('.myclass');
這兩個(gè)方法的參數(shù),可以是逗號(hào)分隔的多個(gè)CSS選擇器,返回匹配其中一個(gè)選擇器的元素節(jié)點(diǎn)。
var matches = document.querySelectorAll('div.note, div.alert');
上面代碼返回class
屬性是note
或alert
的div
元素。
這兩個(gè)方法都支持復(fù)雜的CSS選擇器。
// 選中data-foo-bar屬性等于someval的元素
document.querySelectorAll('[data-foo-bar="someval"]');
// 選中myForm表單中所有不通過驗(yàn)證的元素
document.querySelectorAll('#myForm :invalid');
// 選中div元素,那些class含ignore的除外
document.querySelectorAll('DIV:not(.ignore)');
// 同時(shí)選中div,a,script三類元素
document.querySelectorAll('DIV, A, SCRIPT');
但是,它們不支持CSS偽元素的選擇器(比如:first-line
和:first-letter
)和偽類的選擇器(比如:link
和:visited
),即無法選中偽元素和偽類。
如果querySelectorAll
方法的參數(shù)是字符串*
,則會(huì)返回文檔中的所有HTML元素節(jié)點(diǎn)。另外,querySelectorAll
的返回結(jié)果不是動(dòng)態(tài)集合,不會(huì)實(shí)時(shí)反映元素節(jié)點(diǎn)的變化。
最后,這兩個(gè)方法除了定義在document
對(duì)象上,還定義在元素節(jié)點(diǎn)上,即在元素節(jié)點(diǎn)上也可以調(diào)用。
document.getElementsByTagName
方法返回所有指定HTML標(biāo)簽的元素,返回值是一個(gè)類似數(shù)組的HTMLCollection
對(duì)象,可以實(shí)時(shí)反映HTML文檔的變化。如果沒有任何匹配的元素,就返回一個(gè)空集。
var paras = document.getElementsByTagName('p');
paras instanceof HTMLCollection // true
上面代碼返回當(dāng)前文檔的所有p
元素節(jié)點(diǎn)。
HTML標(biāo)簽名是大小寫不敏感的,因此getElementsByTagName
方法也是大小寫不敏感的。另外,返回結(jié)果中,各個(gè)成員的順序就是它們?cè)谖臋n中出現(xiàn)的順序。
如果傳入*
,就可以返回文檔中所有HTML元素。
var allElements = document.getElementsByTagName('*');
注意,HTML元素本身也定義了getElementsByTagName
方法,返回該元素的后代元素中符合指定標(biāo)簽的元素。也就是說,這個(gè)方法不僅可以在document
對(duì)象上調(diào)用,也可以在任何元素節(jié)點(diǎn)上調(diào)用。
var firstPara = document.getElementsByTagName('p')[0];
var spans = firstPara.getElementsByTagName('span');
上面代碼選中第一個(gè)p
元素內(nèi)部的所有span
元素。
document.getElementsByClassName
方法返回一個(gè)類似數(shù)組的對(duì)象(HTMLCollection
實(shí)例對(duì)象),包括了所有class
名字符合指定條件的元素,元素的變化實(shí)時(shí)反映在返回結(jié)果中。
var elements = document.getElementsByClassName(names);
由于class
是保留字,所以JavaScript一律使用className
表示CSS的class
。
如果參數(shù)是一個(gè)空格分隔的字符串,元素的class
必須符合所有字符串之中所有的class
才會(huì)返回。
var elements = document.getElementsByClassName('foo bar');
上面代碼返回同時(shí)具有foo
和bar
兩個(gè)class
的元素,foo
和bar
的順序不重要。
注意,正常模式下,CSS的class
是大小寫敏感的。(quirks mode
下,大小寫不敏感。)
與getElementsByTagName
方法一樣,getElementsByClassName
方法不僅可以在document
對(duì)象上調(diào)用,也可以在任何元素節(jié)點(diǎn)上調(diào)用。
// 非document對(duì)象上調(diào)用
var elements = rootElement.getElementsByClassName(names);
document.getElementsByName
方法用于選擇擁有name
屬性的HTML元素(比如<form>
、<radio>
、<img>
、<frame>
、<embed>
和<object>
等),返回一個(gè)類似數(shù)組的的對(duì)象(NodeList
對(duì)象的實(shí)例),因?yàn)?code class="highlighter-rouge">name屬性相同的元素可能不止一個(gè)。
// 表單為 <form name="x"></form>
var forms = document.getElementsByName('x');
forms[0].tagName // "FORM"
getElementById
方法返回匹配指定id
屬性的元素節(jié)點(diǎn)。如果沒有發(fā)現(xiàn)匹配的節(jié)點(diǎn),則返回null
。
var elem = document.getElementById('para1');
注意,該方法的參數(shù)是大小寫敏感的。比如,如果某個(gè)節(jié)點(diǎn)的id
屬性是main
,那么document.getElementById('Main')
將返回null
,而不是那個(gè)節(jié)點(diǎn)。
document.getElementById
方法與document.querySelector
方法都能獲取元素節(jié)點(diǎn),不同之處是document.querySelector
方法的參數(shù)使用CSS選擇器語(yǔ)法,document.getElementById
方法的參數(shù)是HTML標(biāo)簽元素的id
屬性。
document.getElementById('myElement')
document.querySelector('#myElement')
上面代碼中,兩個(gè)方法都能選中id
為myElement
的元素,但是getElementById()
比querySelector()
效率高得多。
另外,這個(gè)方法只能在document
對(duì)象上使用,不能在其他元素節(jié)點(diǎn)上使用。
document.elementFromPoint
方法返回位于頁(yè)面指定位置最上層的Element子節(jié)點(diǎn)。
var element = document.elementFromPoint(50, 50);
上面代碼選中在(50, 50)
這個(gè)坐標(biāo)位置的最上層的那個(gè)HTML元素。
elementFromPoint
方法的兩個(gè)參數(shù),依次是相對(duì)于當(dāng)前視口左上角的橫坐標(biāo)和縱坐標(biāo),單位是像素。如果位于該位置的HTML元素不可返回(比如文本框的滾動(dòng)條),則返回它的父元素(比如文本框)。如果坐標(biāo)值無意義(比如負(fù)值或超過視口大?。瑒t返回null
。
以下方法用于生成元素節(jié)點(diǎn)。
document.createElement
方法用來生成網(wǎng)頁(yè)元素節(jié)點(diǎn)。
var newDiv = document.createElement('div');
createElement
方法的參數(shù)為元素的標(biāo)簽名,即元素節(jié)點(diǎn)的tagName
屬性,對(duì)于 HTML 網(wǎng)頁(yè)大小寫不敏感,即參數(shù)為div
或DIV
返回的是同一種節(jié)點(diǎn)。如果參數(shù)里面包含尖括號(hào)(即<
和>
)會(huì)報(bào)錯(cuò)。
document.createElement('<div>')
// DOMException: The tag name provided ('<div>') is not a valid name
document.createTextNode
方法用來生成文本節(jié)點(diǎn),參數(shù)為所要生成的文本節(jié)點(diǎn)的內(nèi)容。
var newDiv = document.createElement('div');
var newContent = document.createTextNode('Hello');
newDiv.appendChild(newContent);
上面代碼新建一個(gè)div
節(jié)點(diǎn)和一個(gè)文本節(jié)點(diǎn),然后將文本節(jié)點(diǎn)插入div
節(jié)點(diǎn)。
這個(gè)方法可以確保返回的節(jié)點(diǎn),被瀏覽器當(dāng)作文本渲染,而不是當(dāng)作HTML代碼渲染。因此,可以用來展示用戶的輸入,避免XSS攻擊。
var div = document.createElement('div');
div.appendChild(document.createTextNode('<span>Foo & bar</span>'));
console.log(div.innerHTML)
// <span>Foo & bar</span>
上面代碼中,createTextNode
方法對(duì)大于號(hào)和小于號(hào)進(jìn)行轉(zhuǎn)義,從而保證即使用戶輸入的內(nèi)容包含惡意代碼,也能正確顯示。
需要注意的是,該方法不對(duì)單引號(hào)和雙引號(hào)轉(zhuǎn)義,所以不能用來對(duì)HTML屬性賦值。
function escapeHtml(str) {
var div = document.createElement('div');
div.appendChild(document.createTextNode(str));
return div.innerHTML;
};
var userWebsite = '" onmouseover="alert(\'derp\')" "';
var profileLink = '<a href="' + escapeHtml(userWebsite) + '">Bob</a>';
var div = document.getElemenetById('target');
div.innerHtml = profileLink;
// <a href="" onmouseover="alert('derp')" "">Bob</a>
上面代碼中,由于createTextNode
方法不轉(zhuǎn)義雙引號(hào),導(dǎo)致onmouseover
方法被注入了代碼。
document.createAttribute
方法生成一個(gè)新的屬性對(duì)象節(jié)點(diǎn),并返回它。
attribute = document.createAttribute(name);
createAttribute方法的參數(shù)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方法生成一個(gè)DocumentFragment對(duì)象。
var docFragment = document.createDocumentFragment();
DocumentFragment對(duì)象是一個(gè)存在于內(nèi)存的DOM片段,但是不屬于當(dāng)前文檔,常常用來生成較復(fù)雜的DOM結(jié)構(gòu),然后插入當(dāng)前文檔。這樣做的好處在于,因?yàn)镈ocumentFragment不屬于當(dāng)前文檔,對(duì)它的任何改動(dòng),都不會(huì)引發(fā)網(wǎng)頁(yè)的重新渲染,比直接修改當(dāng)前文檔的DOM有更好的性能表現(xiàn)。
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);
document.createEvent
方法生成一個(gè)事件對(duì)象,該對(duì)象可以被element.dispatchEvent
方法使用,觸發(fā)指定事件。
var event = document.createEvent(type);
createEvent方法的參數(shù)是事件類型,比如UIEvents、MouseEvents、MutationEvents、HTMLEvents。
var event = document.createEvent('Event');
event.initEvent('build', true, true);
document.addEventListener('build', function (e) {
// ...
}, false);
document.dispatchEvent(event);
以下三個(gè)方法與document
節(jié)點(diǎn)的事件相關(guān)。這些方法都繼承自EventTarget接口,詳細(xì)介紹參見《Event對(duì)象》章節(jié)的《EventTarget》部分。
// 添加事件監(jiān)聽函數(shù)
document.addEventListener('click', listener, false);
// 移除事件監(jiān)聽函數(shù)
document.removeEventListener('click', listener, false);
// 觸發(fā)事件
var event = new Event('click');
document.dispatchEvent(event);
document.hasFocus
方法返回一個(gè)布爾值,表示當(dāng)前文檔之中是否有元素被激活或獲得焦點(diǎn)。
var focused = document.hasFocus();
注意,有焦點(diǎn)的文檔必定被激活(active),反之不成立,激活的文檔未必有焦點(diǎn)。比如如果用戶點(diǎn)擊按鈕,從當(dāng)前窗口跳出一個(gè)新窗口,該新窗口就是激活的,但是不擁有焦點(diǎn)。
以下方法用于遍歷元素節(jié)點(diǎn)。
(1)document.createNodeIterator()
document.createNodeIterator
方法返回一個(gè)DOM的子節(jié)點(diǎn)遍歷器。
var nodeIterator = document.createNodeIterator(
document.body,
NodeFilter.SHOW_ELEMENT
);
上面代碼返回body元素的遍歷器。createNodeIterator方法的第一個(gè)參數(shù)為遍歷器的根節(jié)點(diǎn),第二個(gè)參數(shù)為所要遍歷的節(jié)點(diǎn)類型,這里指定為元素節(jié)點(diǎn)。其他類型還有所有節(jié)點(diǎn)(NodeFilter.SHOW_ALL)、文本節(jié)點(diǎn)(NodeFilter.SHOW_TEXT)、評(píng)論節(jié)點(diǎn)(NodeFilter.SHOW_COMMENT)等。
所謂“遍歷器”,在這里指可以用nextNode方法和previousNode方法依次遍歷根節(jié)點(diǎn)的所有子節(jié)點(diǎn)。
var nodeIterator = document.createNodeIterator(document.body);
var pars = [];
var currentNode;
while (currentNode = nodeIterator.nextNode()) {
pars.push(currentNode);
}
上面代碼使用遍歷器的nextNode方法,將根節(jié)點(diǎn)的所有子節(jié)點(diǎn),按照從頭部到尾部的順序,讀入一個(gè)數(shù)組。nextNode方法先返回遍歷器的內(nèi)部指針?biāo)诘墓?jié)點(diǎn),然后會(huì)將指針移向下一個(gè)節(jié)點(diǎn)。所有成員遍歷完成后,返回null。previousNode方法則是先將指針移向上一個(gè)節(jié)點(diǎn),然后返回該節(jié)點(diǎn)。
var nodeIterator = document.createNodeIterator(
document.body,
NodeFilter.SHOW_ELEMENT
);
var currentNode = nodeIterator.nextNode();
var previousNode = nodeIterator.previousNode();
currentNode === previousNode // true
上面代碼中,currentNode和previousNode都指向同一個(gè)的節(jié)點(diǎn)。
有一個(gè)需要注意的地方,遍歷器返回的第一個(gè)節(jié)點(diǎn),總是根節(jié)點(diǎn)。
(2)document.createTreeWalker()
document.createTreeWalker
方法返回一個(gè)DOM的子樹遍歷器。它與createNodeIterator方法的區(qū)別在于,后者只遍歷子節(jié)點(diǎn),而它遍歷整個(gè)子樹。
document.createTreeWalker
方法的第一個(gè)參數(shù),是所要遍歷的根節(jié)點(diǎn),第二個(gè)參數(shù)指定所要遍歷的節(jié)點(diǎn)類型。
var treeWalker = document.createTreeWalker(
document.body,
NodeFilter.SHOW_ELEMENT
);
var nodeList = [];
while(treeWalker.nextNode()) nodeList.push(treeWalker.currentNode);
上面代碼遍歷body節(jié)點(diǎn)下屬的所有元素節(jié)點(diǎn),將它們插入nodeList數(shù)組。
document.adoptNode
方法將某個(gè)節(jié)點(diǎn),從其原來所在的文檔移除,插入當(dāng)前文檔,并返回插入后的新節(jié)點(diǎn)。
node = document.adoptNode(externalNode);
document.importNode
方法從外部文檔拷貝指定節(jié)點(diǎn),插入當(dāng)前文檔。
var node = document.importNode(externalNode, deep);
document.importNode
方法用于創(chuàng)造一個(gè)外部節(jié)點(diǎn)的拷貝,然后插入當(dāng)前文檔。它的第一個(gè)參數(shù)是外部節(jié)點(diǎn),第二個(gè)參數(shù)是一個(gè)布爾值,表示對(duì)外部節(jié)點(diǎn)是深拷貝還是淺拷貝,默認(rèn)是淺拷貝(false)。雖然第二個(gè)參數(shù)是可選的,但是建議總是保留這個(gè)參數(shù),并設(shè)為true
。
注意,importNode方法
只是拷貝外部節(jié)點(diǎn),這時(shí)該節(jié)點(diǎn)的父節(jié)點(diǎn)是null。下一步還必須將這個(gè)節(jié)點(diǎn)插入當(dāng)前文檔的DOM樹。
var iframe = document.getElementsByTagName('iframe')[0];
var oldNode = iframe.contentWindow.document.getElementById('myNode');
var newNode = document.importNode(oldNode, true);
document.getElementById("container").appendChild(newNode);
上面代碼從iframe
窗口,拷貝一個(gè)指定節(jié)點(diǎn)myNode
,插入當(dāng)前文檔。
這個(gè)方法指向window.getSelection()
,參見window
對(duì)象一節(jié)的介紹。
Copyright©2021 w3cschool編程獅|閩ICP備15016281號(hào)-3|閩公網(wǎng)安備35020302033924號(hào)
違法和不良信息舉報(bào)電話:173-0602-2364|舉報(bào)郵箱:jubao@eeedong.com
掃描二維碼
下載編程獅App
編程獅公眾號(hào)
聯(lián)系方式:
更多建議: