摘要:節(jié)點(diǎn)之間的關(guān)系構(gòu)成了層次,而所有頁面標(biāo)記則表現(xiàn)為一個(gè)以特定節(jié)點(diǎn)為根節(jié)點(diǎn)的樹形結(jié)構(gòu)。此外,包含在列表中的每個(gè)節(jié)點(diǎn)相互之間都是同胞節(jié)點(diǎn)。在瀏覽器中,對象是繼承自類型的一個(gè)實(shí)例,表示整個(gè)頁面。
DOM(文檔對象模型)是針對 HTML 和 XML 文檔的一個(gè) API。DOM 描繪了一個(gè)層次化的節(jié)點(diǎn)樹,允許開發(fā)人員添加、移除和修改頁面的某一部分。
節(jié)點(diǎn)層次DOM 可以將任何 HTML 或 XML 文檔描繪成一個(gè)由多層節(jié)點(diǎn)構(gòu)成的結(jié)構(gòu)。節(jié)點(diǎn)分為幾種不同的類型,每種類型分別表示文檔中不同的信息及(或)標(biāo)記。每個(gè)節(jié)點(diǎn)都擁有各自的特點(diǎn)、數(shù)據(jù)和方法,另外也與其他節(jié)點(diǎn)存在某種關(guān)系。節(jié)點(diǎn)之間的關(guān)系構(gòu)成了層次,而所有頁面標(biāo)記則表現(xiàn)為一個(gè)以特定節(jié)點(diǎn)為根節(jié)點(diǎn)的樹形結(jié)構(gòu)。以下面的 HTML 為例:
Sample Page Hello World!
可以將這個(gè)簡單的 HTML 文檔表示為一個(gè)層次結(jié)構(gòu),如圖下圖所示。
在這個(gè)例子中,文檔元素是文檔的最外層元素,文檔中的其他所有元素都包含在文檔元素中。每個(gè)文檔只能有一個(gè)文檔元素。
每一段標(biāo)記都可以通過樹中的一個(gè)節(jié)點(diǎn)來表示:HTML 元素通過元素節(jié)點(diǎn)表示,特性(attribute)通過特性節(jié)點(diǎn)表示,文檔類型通過文檔類型節(jié)點(diǎn)表示,而注釋則通過注釋節(jié)點(diǎn)表示。總共有12種節(jié)點(diǎn)類型,這些類型都繼承自一個(gè)基類型。
Node 類型DOM1 級(jí)定義了一個(gè) Node 接口,該接口將由 DOM 中的所有節(jié)點(diǎn)類型實(shí)現(xiàn)。這個(gè) Node 接口在 JavaScript 中是作為 Node 類型實(shí)現(xiàn)的;除了 IE 之外,在其他所有瀏覽器中都可以訪問到這個(gè)類型。JavaScript 中的所有節(jié)點(diǎn)類型都繼承自 Node 類型,因此所有節(jié)點(diǎn)類型都共享著相同的基本屬性和方法。
每個(gè)節(jié)點(diǎn)都有一個(gè) nodeType 屬性,用于表明節(jié)點(diǎn)的類型。節(jié)點(diǎn)類型由在 Node 類型中定義的下列12個(gè)數(shù)值常量來表示,任何節(jié)點(diǎn)類型必居其一:
Node.ELEMENT_NODE(1);
Node.ATTRIBUTE_NODE(2);
Node.TEXT_NODE(3);
Node.CDATA_SECTION_NODE(4);
Node.ENTITY_REFERENCE_NODE(5);
Node.ENTITY_NODE(6);
Node.PROCESSING_INSTRUCTION_NODE(7);
Node.COMMENT_NODE(8);
Node.DOCUMENT_NODE(9);
Node.DOCUMENT_TYPE_NODE(10);
Node.DOCUMENT_FRAGMENT_NODE(11);
Node.NOTATION_NODE(12)。
通過比較上面這些常量,可以很容易地確定節(jié)點(diǎn)的類型,例如:
if (someNode.nodeType == Node.ELEMENT_NODE){ // 在IE中無效 console.log("Node is an element."); }
這個(gè)例子比較了 someNode.nodeType 與 Node.ELEMENT_NODE 常量。如果二者相等,則意味著 someNode 確實(shí)是一個(gè)元素。然而,由于 IE 沒有公開 Node 類型的構(gòu)造函數(shù),因此上面的代碼在 IE 中會(huì)導(dǎo)致錯(cuò)誤。為了確??鐬g覽器兼容,最好還是將 nodeType 屬性與數(shù)字值進(jìn)行比較,如下所示:
if (someNode.nodeType == 1){ // 適用于所有瀏覽器 console.log("Node is an element."); }
并不是所有節(jié)點(diǎn)類型都受到 Web 瀏覽器的支持。開發(fā)人員最常用的就是元素和文本節(jié)點(diǎn)。
Node 屬性概述Node 常用屬性主要有以下10個(gè),接下來我們會(huì)著重講解部分屬性。
nodeType:顯示節(jié)點(diǎn)的類型
nodeName:顯示節(jié)點(diǎn)的名稱
nodeValue:顯示節(jié)點(diǎn)的值
attributes:獲取一個(gè)屬性節(jié)點(diǎn)
firstChild:表示某一節(jié)點(diǎn)的第一個(gè)節(jié)點(diǎn)
lastChild:表示某一節(jié)點(diǎn)的最后一個(gè)子節(jié)點(diǎn)
childNodes:表示所在節(jié)點(diǎn)的所有子節(jié)點(diǎn)
parentNode:表示所在節(jié)點(diǎn)的父節(jié)點(diǎn)
nextSibling:緊挨著當(dāng)前節(jié)點(diǎn)的下一個(gè)節(jié)點(diǎn)
previousSibling:緊挨著當(dāng)前節(jié)點(diǎn)的上一個(gè)節(jié)點(diǎn)
nodeName 和 nodeValue 屬性要了解節(jié)點(diǎn)的具體信息,可以使用 nodeName 和 nodeValue 這兩個(gè)屬性。這兩個(gè)屬性的值完全取決于節(jié)點(diǎn)的類型。在使用這兩個(gè)值以前,最好是像下面這樣先檢測一下節(jié)點(diǎn)的類型。
if (someNode.nodeType == 1){ value = someNode.nodeName; // nodeName的值是元素的標(biāo)簽名 }
在這個(gè)例子中,首先檢查節(jié)點(diǎn)類型,看它是不是一個(gè)元素。如果是,則取得并保存 nodeName 的值。對于元素節(jié)點(diǎn),nodeName 中保存的始終都是元素的標(biāo)簽名,而 nodeValue 的值則始終為 null。
節(jié)點(diǎn)關(guān)系文檔中所有的節(jié)點(diǎn)之間都存在這樣或那樣的關(guān)系。節(jié)點(diǎn)間的各種關(guān)系可以用傳統(tǒng)的家族關(guān)系來描述,相當(dāng)于把文檔樹比喻成家譜。
每個(gè)節(jié)點(diǎn)都有一個(gè) childNodes 屬性,其中保存著一個(gè) NodeList 對象。NodeList 是一種類數(shù)組對象,用于保存一組有序的節(jié)點(diǎn),可以通過位置來訪問這些節(jié)點(diǎn)。請注意,雖然可以通過方括號(hào)語法來訪問 NodeList 的值,而且這個(gè)對象也有 length 屬性,但它并不是 Array 的實(shí)例。NodeList 對象的獨(dú)特之處在于,它實(shí)際上是基于 DOM 結(jié)構(gòu)動(dòng)態(tài)執(zhí)行查詢的結(jié)果,因此 DOM 結(jié)構(gòu)的變化能夠自動(dòng)反映在 NodeList 對象中。
下面的例子展示了如何訪問保存在 NodeList 中的節(jié)點(diǎn)——可以通過方括號(hào),也可以使用 item() 方法。
var firstChild = someNode.childNodes[0]; var secondChild = someNode.childNodes.item(1); var count = someNode.childNodes.length;
無論使用方括號(hào)還是使用 item() 方法都沒有問題,但使用方括號(hào)語法看起來與訪問數(shù)組相似,因此頗受一些開發(fā)人員的青睞。另外,要注意 length 屬性表示的是訪問 NodeList 的那一刻,其中包含的節(jié)點(diǎn)數(shù)量。
每個(gè)節(jié)點(diǎn)都有一個(gè) parentNode 屬性,該屬性指向文檔樹中的父節(jié)點(diǎn)。包含在 childNodes 列表中的所有節(jié)點(diǎn)都具有相同的父節(jié)點(diǎn),因此它們的 parentNode 屬性都指向同一個(gè)節(jié)點(diǎn)。此外,包含在 childNodes 列表中的每個(gè)節(jié)點(diǎn)相互之間都是同胞節(jié)點(diǎn)。通過使用列表中每個(gè)節(jié)點(diǎn)的 previousSibling 和 nextSibling 屬性,可以訪問同一列表中的其他節(jié)點(diǎn)。列表中第一個(gè)節(jié)點(diǎn)的 previousSibling 屬性值為 null,而列表中最后一個(gè)節(jié)點(diǎn)的 nextSibling 屬性的值同樣也為 null,如下面的例子所示:
if (someNode.nextSibling === null){ console.log("Last node in the parent’s childNodes list."); } else if (someNode.previousSibling === null){ console.log("First node in the parent’s childNodes list."); }
當(dāng)然,如果列表中只有一個(gè)節(jié)點(diǎn),那么該節(jié)點(diǎn)的 nextSibling 和 previousSibling 都為 null。
父節(jié)點(diǎn)與其第一個(gè)和最后一個(gè)子節(jié)點(diǎn)之間也存在特殊關(guān)系。父節(jié)點(diǎn)的 firstChild 和 lastChild 屬性分別指向其 childNodes 列表中的第一個(gè)和最后一個(gè)節(jié)點(diǎn)。其中,someNode.firstChild 的值始終等于 someNode.childNodes[0],而 someNode.lastChild 的值始終等于 someNode.childNodes [someNode.childNodes.length-1]。在只有一個(gè)子節(jié)點(diǎn)的情況下, firstChild 和 lastChild 指向同一個(gè)節(jié)點(diǎn)。如果沒有子節(jié)點(diǎn),那么 firstChild 和 lastChild 的值均為 null。明確這些關(guān)系能夠?qū)ξ覀儾檎液驮L問文檔結(jié)構(gòu)中的節(jié)點(diǎn)提供極大的便利。下圖形象地展示了上述關(guān)系。
在反映這些關(guān)系的所有屬性當(dāng)中,childNodes 屬性與其他屬性相比更方便一些,因?yàn)橹豁毷褂煤唵蔚年P(guān)系指針,就可以通過它訪問文檔樹中的任何節(jié)點(diǎn)。另外,hasChildNodes() 也是一個(gè)非常有用的方法,這個(gè)方法在節(jié)點(diǎn)包含一或多個(gè)子節(jié)點(diǎn)的情況下返回 true;應(yīng)該說,這是比查詢 childNodes 列表的 length 屬性更簡單的方法。
所有節(jié)點(diǎn)都有的最后一個(gè)屬性是 ownerDocument,該屬性指向表示整個(gè)文檔的文檔節(jié)點(diǎn)。這種關(guān)系表示的是任何節(jié)點(diǎn)都屬于它所在的文檔,任何節(jié)點(diǎn)都不能同時(shí)存在于兩個(gè)或更多個(gè)文檔中。通過這個(gè)屬性,我們可以不必在節(jié)點(diǎn)層次中通過層層回溯到達(dá)頂端,而是可以直接訪問文檔節(jié)點(diǎn)。
操作節(jié)點(diǎn)因?yàn)殛P(guān)系指針都是只讀的,所以 DOM 提供了一些操作節(jié)點(diǎn)的方法。其中,最常用的方法是 appendChild(),用于向 childNodes 列表的末尾添加一個(gè)節(jié)點(diǎn)。添加節(jié)點(diǎn)后,childNodes 的新增節(jié)點(diǎn)、父節(jié)點(diǎn)及以前的最后一個(gè)子節(jié)點(diǎn)的關(guān)系指針都會(huì)相應(yīng)地得到更新。更新完成后,appendChild() 返回新增的節(jié)點(diǎn)。來看下面的例子:
var returnedNode = someNode.appendChild(newNode); console.log(returnedNode == newNode); // true console.log(someNode.lastChild == newNode); // true
如果傳入到 appendChild() 中的節(jié)點(diǎn)已經(jīng)是文檔的一部分了,那結(jié)果就是將該節(jié)點(diǎn)從原來的位置轉(zhuǎn)移到新位置。即使可以將 DOM 樹看成是由一系列指針連接起來的,但任何 DOM 節(jié)點(diǎn)也不能同時(shí)出現(xiàn)在文檔中的多個(gè)位置上。因此,如果在調(diào)用 appendChild() 時(shí)傳入了父節(jié)點(diǎn)的第一個(gè)子節(jié)點(diǎn),那么該節(jié)點(diǎn)就會(huì)成為父節(jié)點(diǎn)的最后一個(gè)子節(jié)點(diǎn),如下面的例子所示。
// someNode 有多個(gè)子節(jié)點(diǎn) var returnedNode = someNode.appendChild(someNode.firstChild); console.log(returnedNode == someNode.firstChild); // false console.log(returnedNode == someNode.lastChild); // true
如果需要把節(jié)點(diǎn)放在 childNodes 列表中某個(gè)特定的位置上,而不是放在末尾,那么可以使用 insertBefore() 方法。這個(gè)方法接受兩個(gè)參數(shù):要插入的節(jié)點(diǎn)和作為參照的節(jié)點(diǎn)。插入節(jié)點(diǎn)后,被插入的節(jié)點(diǎn)會(huì)變成參照節(jié)點(diǎn)的前一個(gè)同胞節(jié)點(diǎn) previousSibling,同時(shí)被方法返回。如果參照節(jié)點(diǎn)是 null,則 insertBefore() 與 appendChild() 執(zhí)行相同的操作,如下面的例子所示。
// 插入后成為最后一個(gè)子節(jié)點(diǎn) returnedNode = someNode.insertBefore(newNode, null); console.log(newNode == someNode.lastChild); // true // 插入后成為第一個(gè)子節(jié)點(diǎn) var returnedNode = someNode.insertBefore(newNode, someNode.firstChild); console.log(returnedNode == newNode); // true console.log(newNode == someNode.firstChild); // true // 插入到最后一個(gè)子節(jié)點(diǎn)前面 returnedNode = someNode.insertBefore(newNode, someNode.lastChild); console.log(newNode == someNode.childNodes[someNode.childNodes.length-2]); // true
前面介紹的 appendChild() 和 insertBefore() 方法都只插入節(jié)點(diǎn),不會(huì)移除節(jié)點(diǎn)。而下面要介紹的 replaceChild() 方法接受的兩個(gè)參數(shù)是:要插入的節(jié)點(diǎn)和要替換的節(jié)點(diǎn)。要替換的節(jié)點(diǎn)將由這個(gè)方法返回并從文檔樹中被移除,同時(shí)由要插入的節(jié)點(diǎn)占據(jù)其位置。來看下面的例子。
// 替換第一個(gè)子節(jié)點(diǎn) var returnedNode = someNode.replaceChild(newNode, someNode.firstChild); // 替換最后一個(gè)子節(jié)點(diǎn) returnedNode = someNode.replaceChild(newNode, someNode.lastChild);
在使用 replaceChild() 插入一個(gè)節(jié)點(diǎn)時(shí),該節(jié)點(diǎn)的所有關(guān)系指針都會(huì)從被它替換的節(jié)點(diǎn)復(fù)制過來。盡管從技術(shù)上講,被替換的節(jié)點(diǎn)仍然還在文檔中,但它在文檔中已經(jīng)沒有了自己的位置。
如果只想移除而非替換節(jié)點(diǎn),可以使用 removeChild() 方法。這個(gè)方法接受一個(gè)參數(shù),即要移除的節(jié)點(diǎn)。被移除的節(jié)點(diǎn)將成為方法的返回值,如下面的例子所示。
// 移除第一個(gè)子節(jié)點(diǎn) var formerFirstChild = someNode.removeChild(someNode.firstChild); // 移除最后一個(gè)子節(jié)點(diǎn) var formerLastChild = someNode.removeChild(someNode.lastChild);
與使用 replaceChild() 方法一樣,通過 removeChild() 移除的節(jié)點(diǎn)仍然為文檔所有,只不過在文檔中已經(jīng)沒有了自己的位置。
前面介紹的四個(gè)方法操作的都是某個(gè)節(jié)點(diǎn)的子節(jié)點(diǎn),也就是說,要使用這幾個(gè)方法必須先取得父節(jié)點(diǎn)(使用 parentNode 屬性)。另外,并不是所有類型的節(jié)點(diǎn)都有子節(jié)點(diǎn),如果在不支持子節(jié)點(diǎn)的節(jié)點(diǎn)上調(diào)用了這些方法,將會(huì)導(dǎo)致錯(cuò)誤發(fā)生。
Document 類型JavaScript 通過 Document 類型表示文檔。在瀏覽器中,document 對象是 HTMLDocument(繼承自 Document 類型)的一個(gè)實(shí)例,表示整個(gè) HTML 頁面。而且,document 對象是 window 對象的一個(gè)屬性,因此可以將其作為全局對象來訪問。Document 節(jié)點(diǎn)具有下列特征:
nodeType 的值為9;
nodeName 的值為 "#document";
nodeValue 的值為 null;
parentNode 的值為 null;
ownerDocument 的值為 null;
其子節(jié)點(diǎn)可能是一個(gè) DocumentType(最多一個(gè))、Element(最多一個(gè))、ProcessingInstruction 或 Comment。
Document 類型可以表示 HTML 頁面或者其他基于 XML 的文檔。不過,最常見的應(yīng)用還是作為 HTMLDocument 實(shí)例的 document 對象。通過這個(gè)文檔對象,不僅可以取得與頁面有關(guān)的信息,而且還能操作頁面的外觀及其底層結(jié)構(gòu)。
文檔的子節(jié)點(diǎn)雖然 DOM 標(biāo)準(zhǔn)規(guī)定 Document 節(jié)點(diǎn)的子節(jié)點(diǎn)可以是DocumentType、Element、ProcessingInstruction 或 Comment,但還有兩個(gè)內(nèi)置的訪問其子節(jié)點(diǎn)的快捷方式。第一個(gè)就是documentElement 屬性,該屬性始終指向 HTML 頁面中的 html 元素。另一個(gè)就是通過 childNodes 列表訪問文檔元素,但通過 documentElement 屬性則能更快捷、更直接地訪問該元素。以下面這個(gè)簡單的頁面為例。
這個(gè)頁面在經(jīng)過瀏覽器解析后,其文檔中只包含一個(gè)子節(jié)點(diǎn),即 html 元素??梢酝ㄟ^ documentElement 或 childNodes 列表來訪問這個(gè)元素,如下所示。
var html = document.documentElement; // 取得對的引用 console.log(html === document.childNodes[0]); // true console.log(html === document.firstChild); // true
這個(gè)例子說明,documentElement、firstChild 和 childNodes[0] 的值相同,都指向 元素。
作為 HTMLDocument 的實(shí)例,document 對象還有一個(gè) body 屬性,直接指向 元素。因?yàn)殚_發(fā)人員經(jīng)常要使用這個(gè)元素,所以 document.body 在 JavaScript 代碼中出現(xiàn)的頻率非常高,其用法如下。
var body = document.body; // 取得對的引用
所有瀏覽器都支持 document.documentElement 和 document.body 屬性。
Document 另一個(gè)可能的子節(jié)點(diǎn)是 DocumentType。通常將 標(biāo)簽看成一個(gè)與文檔其他部分不同的實(shí)體,可以通過 doctype 屬性(在瀏覽器中是 document.doctype )來訪問它的信息。
var doctype = document.doctype; // 取得對的引用
瀏覽器對 document.doctype 的支持差別很大,可以給出如下總結(jié)。
IE8 及之前版本:如果存在文檔類型聲明,會(huì)將其錯(cuò)誤地解釋為一個(gè)注釋并把它當(dāng)作 Comment 節(jié)點(diǎn);而 document.doctype 的值始終為 null。
IE9+ 及 Firefox:如果存在文檔類型聲明,則將其作為文檔的第一個(gè)子節(jié)點(diǎn);document.doctype 是一個(gè) DocumentType 節(jié)點(diǎn),也可以通過 document.firstChild 或 document.childNodes[0] 訪問同一個(gè)節(jié)點(diǎn)。
Safari、Chrome 和 Opera:如果存在文檔類型聲明,則將其解析,但不作為文檔的子節(jié)點(diǎn)。document.doctype 是一個(gè) DocumentType 節(jié)點(diǎn),但該節(jié)點(diǎn)不會(huì)出現(xiàn)在 document.childNodes 中。
由于瀏覽器對 document.doctype 的支持不一致,因此這個(gè)屬性的用處很有限。
文檔信息作為 HTMLDocument 的一個(gè)實(shí)例,document 對象還有一些標(biāo)準(zhǔn)的 Document 對象所沒有的屬性。這些屬性提供了 document 對象所表現(xiàn)的網(wǎng)頁的一些信息。其中第一個(gè)屬性就是 title,包含著
// 取得文檔標(biāo)題 var originalTitle = document.title; // 設(shè)置文檔標(biāo)題 document.title = "New page title";
接下來要介紹的3個(gè)屬性都與對網(wǎng)頁的請求有關(guān),它們是 URL、domain 和 referrer。URL 屬性中包含頁面完整的 URL(即地址欄中顯示的URL),domain 屬性中只包含頁面的域名,而 referrer 屬性中則保存著鏈接到當(dāng)前頁面的那個(gè)頁面的 URL。在沒有來源頁面的情況下,referrer 屬性中可能會(huì)包含空字符串。所有這些信息都存在于請求的 HTTP 頭部,只不過是通過這些屬性讓我們能夠在 JavaScrip 中訪問它們而已,如下面的例子所示。
// 取得完整的URL var url = document.URL; // 取得域名 var domain = document.domain; // 取得來源頁面的URL var referrer = document.referrer;查找元素
說到最常見的 DOM 應(yīng)用,恐怕就要數(shù)取得特定的某個(gè)或某組元素的引用,然后再執(zhí)行一些操作了。取得元素的操作可以使用 document 對象的幾個(gè)方法來完成。其中,Document 類型為此提供了兩個(gè)方法:getElementById() 和 getElementsByTagName()。
第一個(gè)方法,getElementById(),接收一個(gè)參數(shù):要取得的元素的 ID。如果找到相應(yīng)的元素則返回該元素,如果不存在帶有相應(yīng) ID 的元素,則返回 null。注意,這里的 ID 必須與頁面中元素的 id 特性(attribute)嚴(yán)格匹配,包括大小寫。以下面的元素為例。
Some text
可以使用下面的代碼取得這個(gè)元素:
var div = document.getElementById("myDiv"); // 取得元素的引用但是,下面的代碼在除 IE7 及更早版本之外的所有瀏覽器中都將返回 null。
var div = document.getElementById("mydiv"); // 無效的ID(在IE7及更早版本中可以)IE8 及較低版本不區(qū)分 ID 的大小寫,因此 "myDiv" 和 "mydiv" 會(huì)被當(dāng)作相同的元素 ID。如果頁面中多個(gè)元素的ID值相同,getElementById() 只返回文檔中第一次出現(xiàn)的元素。
另一個(gè)常用于取得元素引用的方法是 getElementsByTagName()。這個(gè)方法接受一個(gè)參數(shù),即要取得元素的標(biāo)簽名,而返回的是包含零或多個(gè)元素的 NodeList。在HTML文檔中,這個(gè)方法會(huì)返回一個(gè)HTMLCollection 對象,作為一個(gè)“動(dòng)態(tài)”集合,該對象與 NodeList非常類似。例如,下列代碼會(huì)取得頁面中所有的
元素,并返回一個(gè) HTMLCollection。
var images = document.getElementsByTagName("img");這行代碼會(huì)將一個(gè) HTMLCollection 對象保存在 images 變量中。與 NodeList 對象類似,可以使用方括號(hào)語法或 item() 方法來訪問 HTMLCollection 對象中的項(xiàng)。而這個(gè)對象中元素的數(shù)量則可以通過其 length 屬性取得,如下面的例子所示。
console.log(images.length); // 輸出圖像的數(shù)量 console.log(images[0].src); // 輸出第一個(gè)圖像元素的src特性 console.log(images.item(0).src); // 輸出第一個(gè)圖像元素的src特性HTMLCollection 對象還有一個(gè)方法,叫做 namedItem(),使用這個(gè)方法可以通過元素的 name 特性取得集合中的項(xiàng)。例如,假設(shè)上面提到的頁面中包含如下
元素:
那么就可以通過如下方式從 images 變量中取得這個(gè)
元素:
var myImage = images.namedItem("myImage");在提供按索引訪問項(xiàng)的基礎(chǔ)上,HTMLCollection 還支持按名稱訪問項(xiàng),這就為我們?nèi)〉脤?shí)際想要的元素提供了便利。而且,對命名的項(xiàng)也可以使用方括號(hào)語法來訪問,如下所示:
var myImage = images["myImage"];對 HTMLCollection 而言,我們可以向方括號(hào)中傳入數(shù)值或字符串形式的索引值。在后臺(tái),對數(shù)值索引就會(huì)調(diào)用 item(),而對字符串索引就會(huì)調(diào)用 namedItem()。
要想取得文檔中的所有元素,可以向 getElementsByTagName() 中傳入 "*"。在 JavaScript 及 CSS 中,星號(hào)(*)通常表示“全部”。下面看一個(gè)例子。
var allElements = document.getElementsByTagName("*");僅此一行代碼返回的 HTMLCollection 中,就包含了整個(gè)頁面中的所有元素——按照它們出現(xiàn)的先后順序。換句話說,第一項(xiàng)是 元素,第二項(xiàng)是 元素,以此類推。由于 IE 將注釋(Comment)實(shí)現(xiàn)為元素(Element),因此在IE中調(diào)用 getElementsByTagName("*") 將會(huì)返回所有注釋節(jié)點(diǎn)。
第三個(gè)方法,也是只有 HTMLDocument 類型才有的方法,是 getElementsByName()。顧名思義,這個(gè)方法會(huì)返回帶有給定 name 特性的所有元素。最常使用 getElementsByName() 方法的情況是取得單選按鈕;為了確保發(fā)送給瀏覽器的值正確無誤,所有單選按鈕必須具有相同的 name 特性,如下面的例子所示。
如這個(gè)例子所示,其中所有單選按鈕的 name 特性值都是 "color",但它們的 ID 可以不同。ID 的作用在于將 元素應(yīng)用到每個(gè)單選按鈕,而 name 特性則用以確保三個(gè)值中只有一個(gè)被發(fā)送給瀏覽器。這樣,我們就可以使用如下代碼取得所有單選按鈕:
var radios = document.getElementsByName("color");與 getElementsByTagName() 類似,getElementsByName() 方法也會(huì)返回一個(gè) HTMLCollectioin。但是,對于這里的單選按鈕來說,namedItem() 方法則只會(huì)取得第一項(xiàng)(因?yàn)槊恳豁?xiàng)的 name 特性都相同)。
特殊集合除了屬性和方法,document 對象還有一些特殊的集合。這些集合都是 HTMLCollection 對象,為訪問文檔常用的部分提供了快捷方式,包括:
document.anchors,包含文檔中所有帶 name 特性的 元素;
document.applets,包含文檔中所有的 元素,因?yàn)椴辉偻扑]使用 元素,所以這個(gè)集合已經(jīng)不建議使用了;
document.forms,包含文檔中所有的 元素,與document.getElementsByTagName("form")得到的結(jié)果相同;
document.images,包含文檔中所有的
元素,與document.getElementsByTagName("img")得到的結(jié)果相同;
document.links,包含文檔中所有帶href特性的 元素。
這個(gè)特殊集合始終都可以通過 HTMLDocument 對象訪問到,而且,與 HTMLCollection 對象類似,集合中的項(xiàng)也會(huì)隨著當(dāng)前文檔內(nèi)容的更新而更新。
文檔寫入有一個(gè) document 對象的功能已經(jīng)存在很多年了,那就是將輸出流寫入到網(wǎng)頁中的能力。這個(gè)能力體現(xiàn)在下列4個(gè)方法中:write()、writeln()、open() 和 close()。其中,write() 和 writeln() 方法都接受一個(gè)字符串參數(shù),即要寫入到輸出流中的文本。write() 會(huì)原樣寫入,而 writeln() 則會(huì)在字符串的末尾添加一個(gè)換行符 n。在頁面被加載的過程中,可以使用這兩個(gè)方法向頁面中動(dòng)態(tài)地加入內(nèi)容,如下面的例子所示。
document.write() Example The current date and time is:
這個(gè)例子展示了在頁面加載過程中輸出當(dāng)前日期和時(shí)間的代碼。其中,日期被包含在一個(gè) 元素中,就像在 HTML 頁面中包含普通的文本一樣。這樣做會(huì)創(chuàng)建一個(gè) DOM 元素,而且可以在將來訪問該元素。通過 write() 和 writeln() 輸出的任何 HTML 代碼都將如此處理。
此外,還可以使用 write() 和 writeln() 方法動(dòng)態(tài)地包含外部資源,例如 JavaScript 文件等。在包含 JavaScript 文件時(shí),必須注意不能像下面的例子那樣直接包含字符串 "",因?yàn)檫@會(huì)導(dǎo)致該字符串被解釋為腳本塊的結(jié)束,它后面的代碼將無法執(zhí)行。
document.write() Example 2 ");即使這個(gè)文件看起來沒錯(cuò),但字符串 "" 將被解釋為與外部的 標(biāo)簽匹配,結(jié)果文本 ");將會(huì)出現(xiàn)在頁面中。為避免這個(gè)問題,只需把這個(gè)字符串分開寫即可;第2章也曾經(jīng)提及這個(gè)問題,解決方案如下。
document.write() Example 3 ");字符串 "" 不會(huì)被當(dāng)作外部 標(biāo)簽的關(guān)閉標(biāo)簽,因而頁面中也就不會(huì)出現(xiàn)多余的內(nèi)容了。
前面的例子使用 document.write() 在頁面被呈現(xiàn)的過程中直接向其中輸出了內(nèi)容。如果在文檔加載結(jié)束后再調(diào)用 document.write(),那么輸出的內(nèi)容將會(huì)重寫整個(gè)頁面,如下面的例子所示:
document.write() Example 4 This is some content that you won"t get to see because it will be overwritten.
在這個(gè)例子中,我們使用了 window.onload 事件處理程序,等到頁面完全加載之后延遲執(zhí)行函數(shù)。函數(shù)執(zhí)行之后,字符串 "Hello world!" 會(huì)重寫整個(gè)頁面內(nèi)容。
方法 open() 和 close() 分別用于打開和關(guān)閉網(wǎng)頁的輸出流。如果是在頁面加載期間使用 write() 或 writeln() 方法,則不需要用到這兩個(gè)方法。
關(guān)卡仔細(xì)想想,下面代碼塊會(huì)輸出什么結(jié)果呢?
aaabbbcccaaabbbccc更多aaabbbccc關(guān)注微信公眾號(hào)「劼哥舍」回復(fù)「答案」,獲取關(guān)卡詳解。
關(guān)注 https://github.com/stone0090/javascript-lessons,獲取最新動(dòng)態(tài)。文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/80895.html
摘要:對象數(shù)組初始化表達(dá)式,闖關(guān)記之上文檔對象模型是針對和文檔的一個(gè)。闖關(guān)記之?dāng)?shù)組數(shù)組是值的有序集合。數(shù)組是動(dòng)態(tài)的,根闖關(guān)記之語法的語法大量借鑒了及其他類語言如和的語法。 《JavaScript 闖關(guān)記》之 DOM(下) Element 類型 除了 Document 類型之外,Element 類型就要算是 Web 編程中最常用的類型了。Element 類型用于表現(xiàn) XML 或 HTML 元素...
摘要:瀏覽器只是實(shí)現(xiàn)的宿主環(huán)境之一,其他宿主環(huán)境包括和。年月,版發(fā)布,成為國際標(biāo)準(zhǔn)。事件定義了事件和事件處理的接口。對于已經(jīng)正式納入標(biāo)準(zhǔn)的來說,盡管各瀏覽器都實(shí)現(xiàn)了某些眾所周知的共同特性,但其他特性還是會(huì)因?yàn)g覽器而異。 JavaScript 是面向 Web 的編程語言,絕大多數(shù)現(xiàn)代網(wǎng)站都使用了 JavaScript,并且所有的現(xiàn)代 Web 瀏覽器(電腦,手機(jī),平板)均包含了 JavaScri...
摘要:本課程之所以叫做闖關(guān)記,是因?yàn)椴糠终鹿?jié)精心設(shè)計(jì)了挑戰(zhàn)關(guān)卡,通過提供更多的實(shí)戰(zhàn)機(jī)會(huì),讓大家可以循序漸進(jìn)地有目的地有挑戰(zhàn)地開展學(xué)習(xí)。課程結(jié)構(gòu)及目錄以下目錄只是初步構(gòu)想,課程結(jié)構(gòu)及內(nèi)容會(huì)根據(jù)實(shí)際情況隨時(shí)進(jìn)行調(diào)整。 為何寫作此課程 stone 主要負(fù)責(zé)基于 Web 的企業(yè)內(nèi)部管理系統(tǒng)的開發(fā),雖然能夠熟練地使用 JavaScript,但隨著對 JavaScript 的理解越來越深,才發(fā)現(xiàn)自己尚...
摘要:內(nèi)存回收此時(shí),局部變量就沒有存在的必要了,因此可以釋放它們的內(nèi)存以供將來使用。局部變量會(huì)在它們離開執(zhí)行環(huán)境時(shí)自動(dòng)被解除引用,如下面這個(gè)例子所示手工解除的引用由于局部變量在函數(shù)執(zhí)行完畢后就離開了其執(zhí)行環(huán)境,因此無需我們顯式地去為它解除引用。 JavaScript 具有自動(dòng)垃圾收集機(jī)制(GC:Garbage Collecation),也就是說,執(zhí)行環(huán)境會(huì)負(fù)責(zé)管理代碼執(zhí)行過程中使用的內(nèi)存。而...
摘要:使用元素嵌入代碼時(shí),只需為指定屬性。需要注意的是,帶有屬性的元素不應(yīng)該在其和元素之間再包含額外的代碼。在包含外部文件時(shí),必須將屬性設(shè)置為指向相應(yīng)文件的。所有元素都會(huì)按照他們在頁面中出現(xiàn)的先后順序依次被解析。關(guān)注,獲取最新動(dòng)態(tài)。 當(dāng)學(xué)習(xí)一門新的編程語言的時(shí)候,應(yīng)該邊學(xué)邊做,反復(fù)演練以加深理解。因此,你需要一個(gè) JavaScript 解釋器。幸運(yùn)的是,每一個(gè) Web 瀏覽器都包含一個(gè) Ja...
摘要:節(jié)點(diǎn)具有以下特征的值為的值為元素的標(biāo)簽名的值為可能是或其子節(jié)點(diǎn)可能是或。添加的這些屬性分別對應(yīng)于每個(gè)元素中都存在的下列標(biāo)準(zhǔn)特性。,有關(guān)元素的附加說明信息,一般通過工具提示條顯示出來。 Element 類型 除了 Document 類型之外,Element 類型就要算是 Web 編程中最常用的類型了。Element 類型用于表現(xiàn) XML 或 HTML 元素,提供了對元素標(biāo)簽名、子節(jié)點(diǎn)及特...
閱讀 943·2023-04-26 02:16
閱讀 1240·2019-08-30 15:55
閱讀 2810·2019-08-30 15:53
閱讀 3412·2019-08-29 15:38
閱讀 2921·2019-08-29 13:42
閱讀 2005·2019-08-26 13:34
閱讀 1868·2019-08-26 10:10
閱讀 3100·2019-08-23 14:40