JS权威指南学习笔记之文档结构和遍历

关于nodeType,其中9为Document节点(根),1为Element节点,3为Text节点,8代表Comment节点,11为DocumentFragment节点。

以下代码为实现文档遍历:

一、遍历祖先元素

 1 /**
 2   * 返回元素e的第N层祖先原色,如果祖先不存在或者祖先不是Element则      返回为null
 3   * 如果n为0,则返回e本身,如果n省略,则置为1,返回父元素
 4   * 如果n为其他,则顺利返回
 5 */
 6 function parent(e, n) {
 7     if (n === undefined) n = 1;
 8     while(n-- && e) e = e.parentNode;
 9     if (!e || e.nodeType !== 1) return null;
10     return e;
11 }

二、遍历兄弟元素

/**
 * 返回元素e的第n个兄弟元素
 * 如果e未定义或者0,直接返回本身
 * 当n为正数时,返回后续的第n个兄弟元素
 * 当n为负数时,返回前面的第n个元素
 */
function sibling(e,n) {
    while(e && n !== 0) {  
        if (n > 0) { 
            if (e.nextElementSibling) e = e.nextElementSibling;
            else {
                for(e=e.nextSibling; e && e.nodeType !== 1; e=e.nextSibling)
            }
            n--;
        }
        else {  
            if (e.previousElementSibing) e = e.previousElementSibling;
            else {
                for(e=e.previousSibling; e&&e.nodeType!==1; e=e.previousSibling)
            }
            n++;
        }
    }
    return e;
}

其中里面出现了nextElementSibling和nextSibling,他们属于不同的API,nextSibling属于节点对象树的API,包括了Element和Text对象,而nextElementSibling则属于元素对象树的API,所以当出现非Element元素时执行for(e=e.nextSibling; e && e.nodeType !== 1; e=e.nextSibling)语句。

三、遍历子孙元素

 1 /**
 2   * 返回e的第n个子元素
 3   * 当n为负数时,从后往前计数。0为第一个,-1为倒数第一个,-2为倒数第二个,以此类推
 4   */
 5   
 7 function child(e, n) {
 8     // 当存在children数组时
 9     if (e.children) {                     
10         if (n < 0) n += e.children.length;
11         if (n < 0) return null;    // 依旧为负,则代表不存在这个子元素
12         return e.children[n];              
13     }
14 
15     // 如果e没有children数组时,找到第一个子元素并向前数或者找到最后一个往前数
16  
17     if (n >= 0) { // n为正,往后数
18         // 找到e的第一个元素
19         if (e.firstElementChild) e = e.firstElementChild;
20         else {
21             for(e = e.firstChild; e && e.nodeType !== 1; e = e.nextSibling)
22                 /* 空循环 */;
23         }
24         return sibling(e, n); // Return the nth sibling of the first child
25     }
26     else { // n为负时,由后往前数
27         if (e.lastElementChild) e = e.lastElementChild;
28         else {
29             for(e = e.lastChild; e && e.nodeType !== 1; e=e.previousSibling)
30                 /* 空循环 */;
31         }
32         return sibling(e, n+1); //+1来转化最后一个子元素为最后一个兄弟元素
33     }
34 }

 

posted on 2013-08-13 16:55  水济尘  阅读(183)  评论(0)    收藏  举报