document節(jié)點(diǎn)

概述

document節(jié)點(diǎn)是文檔的根節(jié)點(diǎn),每張網(wǎng)頁(yè)都有自己的document節(jié)點(diǎn)峡蟋。window.document屬性就指向這個(gè)節(jié)點(diǎn)似忧。只要瀏覽器開(kāi)始載入HTML文檔,這個(gè)節(jié)點(diǎn)對(duì)象就存在了班眯,可以直接調(diào)用希停。

document節(jié)點(diǎn)有不同的辦法可以獲取。

  • 對(duì)于正常的網(wǎng)頁(yè)署隘,直接使用documentwindow.document宠能。
  • 對(duì)于iframe載入的網(wǎng)頁(yè),使用iframe節(jié)點(diǎn)的contentDocument屬性磁餐。
  • 對(duì)Ajax操作返回的文檔违崇,使用XMLHttpRequest對(duì)象的responseXML屬性。
  • 對(duì)于包含某個(gè)節(jié)點(diǎn)的文檔诊霹,使用該節(jié)點(diǎn)的ownerDocument屬性羞延。

上面這四種document節(jié)點(diǎn),都部署了Document接口畅哑,因此有共同的屬性和方法肴楷。當(dāng)然,各自也有一些自己獨(dú)特的屬性和方法荠呐,比如HTML和XML文檔的document節(jié)點(diǎn)就不一樣赛蔫。

內(nèi)部節(jié)點(diǎn)屬性

document節(jié)點(diǎn)有很多屬性,其中相當(dāng)一部分屬于快捷方式泥张,指向文檔內(nèi)部的某個(gè)節(jié)點(diǎn)呵恢。

document.doctype,document.documentElement媚创,document.defaultView

對(duì)于HTML文檔來(lái)說(shuō)渗钉,document對(duì)象一般有兩個(gè)子節(jié)點(diǎn)。第一個(gè)子節(jié)點(diǎn)是document.doctype,它是一個(gè)對(duì)象鳄橘,包含了當(dāng)前文檔類(lèi)型(Document Type Declaration声离,簡(jiǎn)寫(xiě)DTD)信息。對(duì)于HTML5文檔瘫怜,該節(jié)點(diǎn)就代表<!DOCTYPE html>术徊。如果網(wǎng)頁(yè)沒(méi)有聲明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.body嗤瞎,document.head

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è)屬性是可寫(xiě)的,如果對(duì)其寫(xiě)入一個(gè)新的節(jié)點(diǎn)浪漠,會(huì)導(dǎo)致原有的所有子節(jié)點(diǎn)被移除陕习。

document.activeElement

document.activeElement屬性返回當(dāng)前文檔中獲得焦點(diǎn)的那個(gè)元素。用戶(hù)通持吩福可以使用Tab鍵移動(dòng)焦點(diǎn)该镣,使用空格鍵激活焦點(diǎn)。比如响谓,如果焦點(diǎn)在一個(gè)鏈接上损合,此時(shí)按一下空格鍵,就會(huì)跳轉(zhuǎn)到該鏈接娘纷。

節(jié)點(diǎn)集合屬性

以下屬性返回文檔內(nèi)部特定元素的集合嫁审,都是類(lèi)似數(shù)組的對(duì)象。這些集合都是動(dòng)態(tài)的赖晶,原節(jié)點(diǎn)有任何變化律适,立刻會(huì)反映在集合中。

document.links,document.forms捂贿,document.images纠修,document.embeds

document.links屬性返回當(dāng)前文檔所有設(shè)定了href屬性的aarea元素。

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元素的idname屬性引用福荸,因此如果一個(gè)元素有idname屬性蕴坪,就可以在上面這四個(gè)屬性上引用。

// HTML代碼為
// <form name="myForm">
document.myForm === document.forms.myForm // true

document.scripts敬锐,document.styleSheets

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)簽有idname屬性径玖,就可以在document.scripts上引用。

// HTML代碼為
// <script id="myScript" >

document.scripts.myScript
// <script id="myScript"></script>

document.styleSheets屬性返回一個(gè)類(lèi)似數(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

document.documentURI屬性和document.URL屬性都返回一個(gè)字符串攻晒,表示當(dāng)前文檔的網(wǎng)址鲁捏。不同之處是documentURI屬性可用于所有文檔(包括 XML 文檔)给梅,URL屬性只能用于 HTML 文檔双揪。

document.URL
// http://www.example.com/about

document.documentURI === document.URL
// true

如果文檔的錨點(diǎn)(#anchor)變化渔期,這兩個(gè)屬性都會(huì)跟著變化疯趟。

document.domain

document.domain屬性返回當(dāng)前文檔的域名信峻。比如盹舞,某張網(wǎng)頁(yè)的網(wǎng)址是 http://www.example.com/hello.html 矾策,domain屬性就等于[www.example.com](http://www.example.com/)。如果無(wú)法獲取域名逃糟,該屬性返回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岳掐。除此之外的寫(xiě)入串述,都是不可以的纲酗。

document.lastModified

document.lastModified屬性返回當(dāng)前文檔最后修改的時(shí)間戳觅赊,格式為字符串吮螺。

document.lastModified
// Tuesday, July 10, 2001 10:19:42

注意鸠补,lastModified屬性的值是字符串紫岩,所以不能用來(lái)直接比較泉蝌,兩個(gè)文檔誰(shuí)的日期更新梨与,需要用Date.parse方法轉(zhuǎn)成時(shí)間戳格式粥鞋,才能進(jìn)行比較呻粹。

if (Date.parse(doc1.lastModified) > Date.parse(doc2.lastModified)) {
  // ...
}

document.location

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 // "passwd"

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.;

也可以指定相對(duì)URL埃疫。

document.location = 'page2.html';

如果指定的是錨點(diǎn)栓霜,瀏覽器會(huì)自動(dòng)滾動(dòng)到錨點(diǎn)處胳蛮。

document.location = '#top';

注意仅炊,采用上面的方法重置URL抚垄,跟用戶(hù)點(diǎn)擊鏈接跳轉(zhuǎn)的效果是一樣的呆馁。上一個(gè)網(wǎng)頁(yè)依然將保存在瀏覽器歷史之中浙滤,點(diǎn)擊“后退”按鈕就可以回到前一個(gè)網(wǎng)頁(yè)畔咧。

如果不希望用戶(hù)看到前一個(gè)網(wǎng)頁(yè)誓沸,可以使用location.replace方法,瀏覽器history對(duì)象就會(huì)用新的網(wǎng)址煮寡,取代當(dāng)前網(wǎng)址幸撕,這樣的話(huà)坐儿,“后退”按鈕就不會(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)起見(jiàn)辆琅,建議優(yōu)先使用window.location婉烟。如果只是單純地獲取當(dāng)前網(wǎng)址似袁,建議使用document.URL,語(yǔ)義性更好而涉。

document.referrer啼县,document.title季眷,document.characterSet

document.referrer屬性返回一個(gè)字符串瘟裸,表示當(dāng)前文檔的訪(fǎng)問(wèn)來(lái)源话告,如果是無(wú)法獲取來(lái)源或是用戶(hù)直接鍵入網(wǎng)址佛呻,而不是從其他網(wǎng)頁(yè)點(diǎn)擊吓著,則返回一個(gè)空字符串绑莺。

document.referrer的值纺裁,總是與HTTP頭信息的Referer保持一致,但是它的拼寫(xiě)有兩個(gè)r谚殊。

document.title屬性返回當(dāng)前文檔的標(biāo)題嫩絮,該屬性是可寫(xiě)的剿干。

document.title = '新標(biāo)題';

document.characterSet屬性返回渲染當(dāng)前文檔的字符集派敷,比如UTF-8篮愉、ISO-8859-1试躏。

document.readyState

document.readyState屬性返回當(dāng)前文檔的狀態(tài)颠蕴,共有三種可能的值椅您。

  • loading:加載HTML代碼階段(尚未完成解析)
  • interactive:加載外部資源階段時(shí)
  • complete:加載完成時(shí)

這個(gè)屬性變化的過(guò)程如下掀泳。

  1. 瀏覽器開(kāi)始解析HTML文檔员舵,document.readyState屬性等于loading庄拇。
  2. 瀏覽器遇到HTML文檔中的<script>元素丛忆,并且沒(méi)有asyncdefer屬性熄诡,就暫停解析,開(kāi)始執(zhí)行腳本袜茧,這時(shí)document.readyState屬性還是等于loading笛厦。
  3. HTML文檔解析完成,document.readyState屬性變成interactive姨谷。
  4. 瀏覽器等待圖片梦湘、樣式表捌议、字體文件等外部資源加載完成管挟,一旦全部加載完成僻孝,document. readyState屬性變成complete

下面的代碼用來(lái)檢查網(wǎng)頁(yè)是否加載成功荞雏。

// 基本檢查
if (document.readyState === 'complete') {
  // ...
}

// 輪詢(xún)檢查
var interval = setInterval(function() {
  if (document.readyState === 'complete') {
    clearInterval(interval);
    // ...
  }
}, 100);

document.designMode

document.designMode屬性控制當(dāng)前文檔是否可編輯,通常用在制作所見(jiàn)即所得編輯器筑辨。打開(kāi)iframe元素包含的文檔的designMode屬性棍辕,就能將其變?yōu)橐粋€(gè)所見(jiàn)即所得的編輯器。

<iframe id="editor" src="about:blank"></iframe>
<script>
!(function () {
  var editor = document.getElementById('editor');
  editor.contentDocument.designMode = 'on';
})();
</script>

document.implementation

document.implementation屬性返回一個(gè)對(duì)象抚太,用來(lái)甄別當(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版。

document.compatMode

compatMode屬性返回瀏覽器處理文檔的模式仁卷,可能的值為BackCompat(向后兼容模式)和CSS1Compat(嚴(yán)格模式)。

一般來(lái)說(shuō)丰介,如果網(wǎng)頁(yè)代碼的第一行設(shè)置了明確的DOCTYPE(比如<!doctype html>)哮幢,document.compatMode的值都為CSS1Compat

document.cookie

document.cookie屬性用來(lái)操作瀏覽器Cookie钢悲,詳見(jiàn)《瀏覽器環(huán)境》一章的《Cookie》部分。

讀寫(xiě)相關(guān)的方法

document.write()惭等,document.writeln()

document.write方法用于向當(dāng)前文檔寫(xiě)入內(nèi)容。只要當(dāng)前文檔還沒(méi)有用close方法關(guān)閉秤茅,它所寫(xiě)入的內(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)容,然后再寫(xiě)入诞挨。

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è)面渲染過(guò)程中調(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>

在瀏覽器打開(kāi)上面網(wǎng)頁(yè)达罗,將會(huì)顯示hello world坝撑。

document.write是JavaScript語(yǔ)言標(biāo)準(zhǔn)化之前就存在的方法,現(xiàn)在完全有更符合標(biāo)準(zhǔn)的方法向文檔寫(xiě)入內(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è)上顯示不出換行叠纹。

查找節(jié)點(diǎn)的方法

以下方法用來(lái)查找某個(gè)節(jié)點(diǎn)季研。

document.querySelector(),document.querySelectorAll()

document.querySelector方法接受一個(gè)CSS選擇器作為參數(shù)誉察,返回匹配該選擇器的元素節(jié)點(diǎn)与涡。如果有多個(gè)節(jié)點(diǎn)滿(mǎn)足匹配條件,則返回第一個(gè)匹配的節(jié)點(diǎn)持偏。如果沒(méi)有發(fā)現(xiàn)匹配的節(jié)點(diǎn)驼卖,則返回null

var el1 = document.querySelector('.myclass');
var el2 = document.querySelector('#myParent > [ng-click]');

document.querySelectorAll方法與querySelector用法類(lèi)似鸿秆,區(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屬性是notealertdiv元素。

這兩個(gè)方法都支持復(fù)雜的CSS選擇器埠戳。

// 選中data-foo-bar屬性等于someval的元素
document.querySelectorAll('[data-foo-bar="someval"]');

// 選中myForm表單中所有不通過(guò)驗(yàn)證的元素
document.querySelectorAll('#myForm :invalid');

// 選中div元素,那些class含ignore的除外
document.querySelectorAll('DIV:not(.ignore)');

// 同時(shí)選中div蕉扮,a整胃,script三類(lèi)元素
document.querySelectorAll('DIV, A, SCRIPT');

但是,它們不支持CSS偽元素的選擇器(比如:first-line:first-letter)和偽類(lèi)的選擇器(比如:link:visited)喳钟,即無(wú)法選中偽元素和偽類(lèi)屁使。

如果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()

document.getElementsByTagName方法返回所有指定HTML標(biāo)簽的元素,返回值是一個(gè)類(lèi)似數(shù)組的HTMLCollection對(duì)象食铐,可以實(shí)時(shí)反映HTML文檔的變化匕垫。如果沒(méi)有任何匹配的元素,就返回一個(gè)空集虐呻。

var paras = document.getElementsByTagName('p');

paras instanceof HTMLCollection // true

上面代碼返回當(dāng)前文檔的所有p元素節(jié)點(diǎn)象泵。

HTML標(biāo)簽名是大小寫(xiě)不敏感的蚊伞,因此getElementsByTagName方法也是大小寫(xiě)不敏感的饺律。另外棵帽,返回結(jié)果中寿羞,各個(gè)成員的順序就是它們?cè)谖臋n中出現(xiàn)的順序喊熟。

如果傳入*息裸,就可以返回文檔中所有HTML元素疯兼。

var allElements = document.getElementsByTagName('*');

注意教馆,HTML元素本身也定義了getElementsByTagName方法馋缅,返回該元素的后代元素中符合指定標(biāo)簽的元素扒腕。也就是說(shuō),這個(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()

document.getElementsByClassName方法返回一個(gè)類(lèi)似數(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í)具有foobar兩個(gè)class的元素析藕,foobar的順序不重要召廷。

注意,正常模式下账胧,CSS的class是大小寫(xiě)敏感的竞慢。(quirks mode下,大小寫(xiě)不敏感治泥。)

getElementsByTagName方法一樣筹煮,getElementsByClassName方法不僅可以在document對(duì)象上調(diào)用,也可以在任何元素節(jié)點(diǎn)上調(diào)用居夹。

// 非document對(duì)象上調(diào)用
var elements = rootElement.getElementsByClassName(names);

document.getElementsByName()

document.getElementsByName方法用于選擇擁有name屬性的HTML元素(比如<form>败潦、<radio><img>准脂、<frame>变屁、<embed><object>等),返回一個(gè)類(lèi)似數(shù)組的的對(duì)象(NodeList對(duì)象的實(shí)例)意狠,因?yàn)?code>name屬性相同的元素可能不止一個(gè)粟关。

// 表單為 <form name="x"></form>
var forms = document.getElementsByName('x');
forms[0].tagName // "FORM"

getElementById()

getElementById方法返回匹配指定id屬性的元素節(jié)點(diǎn)。如果沒(méi)有發(fā)現(xiàn)匹配的節(jié)點(diǎn)环戈,則返回null闷板。

var elem = document.getElementById('para1');

注意,該方法的參數(shù)是大小寫(xiě)敏感的院塞。比如遮晚,如果某個(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è)方法都能選中idmyElement的元素顶瞒,但是getElementById()querySelector()效率高得多夸政。

另外,這個(gè)方法只能在document對(duì)象上使用榴徐,不能在其他元素節(jié)點(diǎn)上使用守问。

document.elementFromPoint()

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)值無(wú)意義(比如負(fù)值或超過(guò)視口大小)探越,則返回null狡赐。

生成節(jié)點(diǎn)的方法

以下方法用于生成元素節(jié)點(diǎn)窑业。

document.createElement()

document.createElement方法用來(lái)生成網(wǎng)頁(yè)元素節(jié)點(diǎn)钦幔。

var newDiv = document.createElement('div');

createElement方法的參數(shù)為元素的標(biāo)簽名,即元素節(jié)點(diǎn)的tagName屬性常柄,對(duì)于 HTML 網(wǎng)頁(yè)大小寫(xiě)不敏感鲤氢,即參數(shù)為divDIV返回的是同一種節(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()

document.createTextNode方法用來(lái)生成文本節(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代碼渲染寝并。因此,可以用來(lái)展示用戶(hù)的輸入腹备,避免XSS攻擊衬潦。

var div = document.createElement('div');
div.appendChild(document.createTextNode('<span>Foo & bar</span>'));
console.log(div.innerHTML)
// &lt;span&gt;Foo &amp; bar&lt;/span&gt;

上面代碼中,createTextNode方法對(duì)大于號(hào)和小于號(hào)進(jìn)行轉(zhuǎn)義植酥,從而保證即使用戶(hù)輸入的內(nèi)容包含惡意代碼镀岛,也能正確顯示。

需要注意的是友驮,該方法不對(duì)單引號(hào)和雙引號(hào)轉(zhuǎn)義漂羊,所以不能用來(lái)對(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.getElementById('target');
div.innerHTML = profileLink;
// <a href="" onmouseover="alert('derp')" "">Bob</a>

上面代碼中卸留,由于createTextNode方法不轉(zhuǎn)義雙引號(hào)拨与,導(dǎo)致onmouseover方法被注入了代碼。

document.createAttribute()

document.createAttribute方法生成一個(gè)新的屬性對(duì)象節(jié)點(diǎn)艾猜,并返回它买喧。

attribute = document.createAttribute(name);

createAttribute方法的參數(shù)name捻悯,是屬性的名稱(chēng)。

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");

document.createDocumentFragment()

createDocumentFragment方法生成一個(gè)DocumentFragment對(duì)象淤毛。

var docFragment = document.createDocumentFragment();

DocumentFragment對(duì)象是一個(gè)存在于內(nèi)存的DOM片段今缚,但是不屬于當(dāng)前文檔,常常用來(lái)生成較復(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);

事件相關(guān)的方法

document.createEvent()

document.createEvent方法生成一個(gè)事件對(duì)象餐塘,該對(duì)象可以被element.dispatchEvent方法使用,觸發(fā)指定事件皂吮。

var event = document.createEvent(type);

createEvent方法的參數(shù)是事件類(lèi)型戒傻,比如UIEvents、MouseEvents蜂筹、MutationEvents需纳、HTMLEvents。

var event = document.createEvent('Event');
event.initEvent('build', true, true);
document.addEventListener('build', function (e) {
  // ...
}, false);
document.dispatchEvent(event);

document.addEventListener()艺挪,document.removeEventListener()不翩,document.dispatchEvent()

以下三個(gè)方法與document節(jié)點(diǎn)的事件相關(guān)。這些方法都繼承自EventTarget接口麻裳,詳細(xì)介紹參見(jiàn)《Event對(duì)象》章節(jié)的《EventTarget》部分口蝠。

// 添加事件監(jiān)聽(tīng)函數(shù)
document.addEventListener('click', listener, false);

// 移除事件監(jiān)聽(tīng)函數(shù)
document.removeEventListener('click', listener, false);

// 觸發(fā)事件
var event = new Event('click');
document.dispatchEvent(event);

其他方法

document.hasFocus()

document.hasFocus方法返回一個(gè)布爾值,表示當(dāng)前文檔之中是否有元素被激活或獲得焦點(diǎn)掂器。

var focused = document.hasFocus();

注意亚皂,有焦點(diǎn)的文檔必定被激活(active),反之不成立国瓮,激活的文檔未必有焦點(diǎn)灭必。比如如果用戶(hù)點(diǎn)擊按鈕,從當(dāng)前窗口跳出一個(gè)新窗口乃摹,該新窗口就是激活的禁漓,但是不擁有焦點(diǎn)。

document.createNodeIterator()孵睬,document.createTreeWalker()

以下方法用于遍歷元素節(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)類(lèi)型叭莫,這里指定為元素節(jié)點(diǎn)。其他類(lèi)型還有所有節(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的子樹(shù)遍歷器僚祷。它與createNodeIterator方法的區(qū)別在于佛致,后者只遍歷子節(jié)點(diǎn),而它遍歷整個(gè)子樹(shù)辙谜。

document.createTreeWalker方法的第一個(gè)參數(shù)俺榆,是所要遍歷的根節(jié)點(diǎn),第二個(gè)參數(shù)指定所要遍歷的節(jié)點(diǎn)類(lèi)型装哆。

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()

document.adoptNode方法將某個(gè)節(jié)點(diǎn)蜕琴,從其原來(lái)所在的文檔移除萍桌,插入當(dāng)前文檔,并返回插入后的新節(jié)點(diǎn)凌简。

node = document.adoptNode(externalNode);

document.importNode()

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樹(shù)。

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)前文檔。

document.getSelection()

這個(gè)方法指向window.getSelection()享扔,參見(jiàn)window對(duì)象一節(jié)的介紹底桂。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市惧眠,隨后出現(xiàn)的幾起案子籽懦,更是在濱河造成了極大的恐慌,老刑警劉巖氛魁,帶你破解...
    沈念sama閱讀 207,248評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件暮顺,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡秀存,警方通過(guò)查閱死者的電腦和手機(jī)捶码,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,681評(píng)論 2 381
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)或链,“玉大人惫恼,你說(shuō)我怎么就攤上這事“难危” “怎么了祈纯?”我有些...
    開(kāi)封第一講書(shū)人閱讀 153,443評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀(guān)的道長(zhǎng)洞就。 經(jīng)常有香客問(wèn)我盆繁,道長(zhǎng),這世上最難降的妖魔是什么旬蟋? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,475評(píng)論 1 279
  • 正文 為了忘掉前任油昂,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘冕碟。我一直安慰自己拦惋,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,458評(píng)論 5 374
  • 文/花漫 我一把揭開(kāi)白布安寺。 她就那樣靜靜地躺著厕妖,像睡著了一般。 火紅的嫁衣襯著肌膚如雪挑庶。 梳的紋絲不亂的頭發(fā)上言秸,一...
    開(kāi)封第一講書(shū)人閱讀 49,185評(píng)論 1 284
  • 那天,我揣著相機(jī)與錄音迎捺,去河邊找鬼举畸。 笑死,一個(gè)胖子當(dāng)著我的面吹牛凳枝,可吹牛的內(nèi)容都是我干的抄沮。 我是一名探鬼主播,決...
    沈念sama閱讀 38,451評(píng)論 3 401
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼岖瑰,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼叛买!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起蹋订,我...
    開(kāi)封第一講書(shū)人閱讀 37,112評(píng)論 0 261
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤率挣,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后辅辩,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體难礼,經(jīng)...
    沈念sama閱讀 43,609評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡娃圆,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,083評(píng)論 2 325
  • 正文 我和宋清朗相戀三年玫锋,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片讼呢。...
    茶點(diǎn)故事閱讀 38,163評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡撩鹿,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出悦屏,到底是詐尸還是另有隱情节沦,我是刑警寧澤,帶...
    沈念sama閱讀 33,803評(píng)論 4 323
  • 正文 年R本政府宣布础爬,位于F島的核電站甫贯,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏看蚜。R本人自食惡果不足惜叫搁,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,357評(píng)論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧渴逻,春花似錦疾党、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,357評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至梨撞,卻和暖如春雹洗,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背卧波。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,590評(píng)論 1 261
  • 我被黑心中介騙來(lái)泰國(guó)打工队伟, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人幽勒。 一個(gè)月前我還...
    沈念sama閱讀 45,636評(píng)論 2 355
  • 正文 我出身青樓嗜侮,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親啥容。 傳聞我的和親對(duì)象是個(gè)殘疾皇子锈颗,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,925評(píng)論 2 344

推薦閱讀更多精彩內(nèi)容