南昌莫非:childNodes、parentNode、previousSibling、nextSibling、firstChild和lastChild屬性使用方法
文檔中所有的節(jié)點之間都存在這樣或那樣的關(guān)系。節(jié)點間的各種關(guān)系可以用傳統(tǒng)的家族關(guān)系來描述,相當于把文檔樹比喻成家譜。在HTML中,可以將<body>元素看成是<html>元素的子元素;相應(yīng)地,也就可以將<html>元素看成是<body>元素的父元素。而<head>元素,則可以看成是<body>元素的同胞元素,因為它們都是同一個父元素<html>的直接子元素。
每個節(jié)點都有一個childNodes屬性,其中保存著一個NodeLiist對象。NodeList是一種類數(shù)組對象,用于保存一組有序的節(jié)點,可以通過位置來訪問這些節(jié)點。請注意,雖然可以通過方括號語法來訪問NodeList的值,而且這個對象也有l(wèi)ength屬性,但它并不是Array的實例。NodeList對象的獨特之處在于,它實際上是基于DOM結(jié)構(gòu)動態(tài)執(zhí)行查詢的結(jié)果,因此DOM結(jié)構(gòu)的變化能夠自動反映在NodeList對象中。我們常說,NodeList是有生命、有呼吸的對象,而不是在我們**次訪問它們的某個瞬間拍攝下來的一張快照。
下面的例子展示了如何訪問保存在NodeList中的節(jié)點——可以通過方括號,也可以使用item()
方法:
var firstChild=someNode.childNodes[0];
var secondChild=someNode.childNodes.item (1);
var count=someNode.childNodes.length;
無論使用方括號還是使用item()方法都沒有問題,但使用方括號語法看起來與訪問數(shù)組相似,因此頗受一些開發(fā)人員的青睞。另外,要注意length屬性表示的是訪問NodeList的那一刻,其中包含的節(jié)點數(shù)量。我們在本書前面介紹過,對arguments對象使用Array.prototype.slice()方法;可以將其轉(zhuǎn)換為數(shù)組。而采用同樣的方法,也可以將NodeList對象轉(zhuǎn)換為數(shù)組。來看下面的例子:
//在IE中無效
var arrayofNodes=Array.prototype.slice.call( someNode.childNodes,0);
除IE之外,這行代碼能在任何瀏覽器中運行。由于IE將NodeList實現(xiàn)為一個COM對象,而我們不能像使用JScript對象那樣使用這種對象,因此上面的代碼在IE中會導(dǎo)致錯誤。要想在IE中將NodeList轉(zhuǎn)換為數(shù)組,必須手動枚舉所有成員。下列代碼在所有瀏覽器中都可以運行:
function convertToArray( nodes){
var array=null;
try{
array=Array.prototype.slice.call( nodes,0);//針對非IE瀏覽器
) catch (ex) {
array=new Array();
for (var i=0. len=nodes.length;i<len; i++){
array.push (nodes [i]);
}
}
return array;
}
這個convertToArray()函數(shù)首先嘗試了創(chuàng)建數(shù)組的最簡單方式。如果導(dǎo)致了錯誤(說明是在IE中),則通過try-catch塊來捕獲錯誤,然后手動創(chuàng)建數(shù)組。這是另一種檢測怪癖的形式。
每個節(jié)點都有一個parentNode屬性.該屬性指向文檔樹中的父節(jié)點。包含在childNodes列表中的所有節(jié)點都具有相同的父節(jié)點,因此它們的parentNode屬性都指向同一個節(jié)點。此外,包含在childNodes列表中的每個節(jié)點相互之間都是同胞節(jié)點。通過使用列表中每個節(jié)點的previousSibling和nextSibling屬性,可以訪問同一列表中的其他節(jié)點。列表中**個節(jié)點的previousSibling屬性值為null,向列表中最后一個節(jié)點的nextSibling屬性的值同樣也為null,如下面的例子所示:
if ( someNode.nextSibling===null)(
alert("Last node in the parent ' s childlNodes list.");
} else if (someNode.previousSibling===null){
alert("First node in the parent' s childNodes list.");
}
當然,南昌網(wǎng)站設(shè)計公司技術(shù)人員提示如果列表中只有一個節(jié)點,那么該節(jié)點的nextSibling和previousSibling都為null。
父節(jié)點與其**個和最后一個子節(jié)點之間也存在特殊關(guān)系。父節(jié)點的firstChild和lastChild屬性分別指向其childNodes列表中的**個和最后一個節(jié)點。其中,someNode.firstChild的值始終等于someNode.childNodes[O],而someNode.lasChild的值始終等于someNode.childNodes[someNode.childNodes.length-l]。在只有一個子節(jié)點的情況下,firstChild和lastChild指向同一個節(jié)點。如果沒有子節(jié)點,那么firstChild和lastChild的值均為null。明確這些關(guān)系能夠?qū)ξ覀儾檎液驮L問文檔結(jié)構(gòu)中的節(jié)點提供極大的便利。圖10-2形象地展示了上述關(guān)系。
在反映這些關(guān)系的所有屬性當中,childNodes屬性與其他屬性相比更方便一些,因為只須使用簡單的關(guān)系指針,就可以通過它訪問文檔樹中的任何節(jié)點。另外,hasChildNodes()也是一個非常有
用的方法,這個方法在節(jié)點包含一或多個子節(jié)點的情況下返回true;應(yīng)該說,這是比查詢childNodes
列表的length屬性更簡單的方法。
所有節(jié)點都有的最后一個屬性是ownerDocument,該屬性指向表示整個文檔的文檔節(jié)點。這種關(guān)系表示的是任何節(jié)點都屬于它所在的文檔,任何節(jié)點都不能同時存在于兩個或更多個文檔中。通過這個屬性,我們可以不必在節(jié)點層次中通過層層回溯到達頂端,而是可以直接訪問文檔節(jié)點。
雖然所有節(jié)點類型都繼承自Node,但并不是每種節(jié)點都有子節(jié)點,我們將會討論不同節(jié)點類型之間的差異.