Skip to content
html
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  <!-- 
    节点:Node(页面中所有东西都是节点)
      元素节点(元素标签)
        nodeType:1,节点类型
        nodeName:大写标签名,节点名
        nodeValue: null,节点值
      文本节点
        nodeType:3
        nodeName:'#text'
        nodeValue/textContent: 文本内容
      注释节点
        nodeType:8
        nodeName:'#comment'
        nodeValue: 注释内容
      文档节点 document
        nodeType:9
        nodeName:'#document'
        nodeValue: null
      ...

    节点集合:NodeList(getElementsByClassName、querySelector...获取的是节点集合)
   -->

   <!-- 
     描述节点之间的关系(以下都是属性,不是方法)
      parentNode:获取父节点
      childNodes:获取所有子节点集合(拿不到孙节点)
      children:获取所有的子元素节点集合((拿不到孙节点, 另外低版本IE会把注释当作元素子节点)
      firstChild:获取第一个子节点
      lastChild:获取最后一个子节点
      firstElementChild:获取第一个元素子节点(不兼容IE6-8)
      lastElementChild:获取最后一个元素子节点(不兼容IE6-8)
      previousSibling:获取上一个兄弟节点
      nextSibling:获取下一个兄弟节点
      previousElementSibling:获取上一个兄弟元素节点(不兼容IE6-8)
      lastElementSibling:获取下一个兄弟元素节点(不兼容IE6-8)
      parent.contains(ele) 返回一个布尔值, 来表示ele是否为parent后代节点。
      ...
    -->

    <!-- 
      document.parentNode和document.parentnode的值分别是多少
        body -> html -> document
        document.parentNode是找document的父节点,document已经是最外层了,
        所以document.parentNode值为null
        而document.parentnode是去document上找属性名为parentnode的值,结果为undefined
     -->

    <div id="box">
      <!-- 注释 -->
      <li>1</li>
      <li id="li2">2</li>
      <li>3</li>
      <li>4</li>
      <li>5</li>
    </div>

    <script>
      const box = document.querySelector('#box')
      // 标准浏览器(非IE6-8)中会把空格和换行当作文本节点处理
      // console.log(box.childNodes)
      // 只获取li(IE6-8下使用children会把注释节点也当作元素节点)
      // console.log(box.children)
      
      // 获取指定上下文中所有的子元素节点
      function children (context) {
        // 1.获取所有子节点
        var res = [],
          nodeList = context.childNodes

        // 2.获取nodeType === 1的子节点
        for (var i = 0; i < nodeList.length; i++) {
          var item = nodeList[i]
          item.nodeType === 1 ? res.push(nodeList[i]) : null
        }

        return res
      }

      // 获取上一个兄弟元素节点
      function prev (context) {
        var pre = context.previousSibling
        while(pre.nodeType !== 1) {
          pre = pre.previousSibling
        }
        return pre
      }
    
      // 获取当前元素之前的所有兄弟元素节点
      // function prevAll (context) {
      //   let result = [],
      //     parent = context.parentNode,
      //     nodeList = parent.childNodes
        
      //   for (let i = 0; i < nodeList.length; i++) {
      //     if (nodeList[i] === context) break
      //     if (nodeList[i].nodeType === 1) result.push(nodeList[i])
      //   }

      //   return result
      // }

      function prevAll (context) {
        let result = [],
          // 获取当前元素上一个兄弟元素节点
          prev = context.previousSibling
        while (prev) {
          // 如果存在,看是不是元素节点,是就添加到数组末尾
          if (prev.nodeType === 1) result.unshift(prev)
          // 添加后再找上一个兄弟元素节点
          prev = prev.previousSibling
        }
        return result
      }

      // 获取当前元素下一个兄弟元素
      function next (context) {
        let next = context.nextSibling
        while(next.nodeType !== 1) {
          next = next.nextSibling
        }
        return next
      }

      // 获取当前元素之后的所有兄弟元素节点
      // function nextAll (context) {
      //   let result = [],
      //     parent = context.parentNode,
      //     nodeList = parent.childNodes
        
      //   for (let i = nodeList.length - 1; i > 0; i--) {
      //     if (nodeList[i] === context) break 
      //     if (nodeList[i].nodeType === 1) {
      //       result.unshift(nodeList[i])
      //     }
      //   }

      //   return result
      // }

      function nextAll (context) {
        let result = [],
          next = context.nextSibling
          
        while (next) {
          if (next.nodeType === 1) result.push(next)
          next = next.nextSibling
        }

        return result
      }

      // 获取当前元素的所有兄弟元素节点
      function siblings (context) {
        return prevAll(context).concat(nextAll(context))        
      }

      // 获取当前元素在兄弟元素中的索引
      function index (context) {
        // 前面有几个兄弟,索引就是几
        return prevAll(context).length
      }
    </script>
</body>
</html>