ThinkChat2.0新版上线,更智能更精彩,支持会话、画图、阅读、搜索等,送10W Token,即刻开启你的AI之旅 广告
[toc] # 每日英语 1. `Uniform` 统一 2. `Resource` 资源 # DOM 概述 ## DOM 1. DOM 是 JavaScript 操作网页的接口,全称为“文档对象模型”(Document Object Model)。 1. 它的作用是将网页转为一个 JavaScript 对象,从而可以用脚本进行各种操作(比如增删内容)。 1. 浏览器会根据 DOM 模型,将结构化文档(比如 HTML 和 XML)解析成一系列的节点,再由这些节点组成一个树状结构(DOM Tree)。 1. 所有的节点和最终的树状结构,都有规范的对外接口。 1. DOM 操作是 JavaScript 最常见的任务,离开了 DOM,JavaScript 就无法控制网页 ## 节点 > DOM 的最小组成单位叫做节点(node)。 > 文档的树形结构(DOM 树),就是由各种不同类型的节点组成。 > 每个节点可以看作是文档树的一片叶子。 节点的类型有七种。 1. `Document`:整个文档树的顶层节点 1. `Element`:网页的各种 HTML 标签(比如<body>、<a>等) 1. `Attribute`:网页元素的属性(比如 class="right") 1. `Text`:标签之间或标签包含的文本 1. `Comment`:注释 > 浏览器提供一个原生的节点对象 Node, > 上面这七种节点都继承了 Node,因此具有一些共同的属性和方法。 ## 节点树 > 一个文档的所有节点,按照所在的层级,可以抽象成一种树状结构。这种树状结构就是 DOM 树。 > 它有一个顶层节点,下一层都是顶层节点的子节点,然后子节点又有自己的子节点,就这样层层衍生出一个金字塔结构,倒过来就像一棵树。 _浏览器原生提供 document 节点,代表整个文档。_ > 控制台输出 document, 会是什么? 文档的第一层只有一个节点,就是 HTML 网页的第一个标签<html> 它构成了树结构的根节点(root node),其他 HTML 标签节点都是它的下级节点。 除了根节点,其他节点都有三种层级关系。 1. 父节点关系(`parentNode`):直接的那个上级节点 1. 子节点关系(`childNodes`):直接的下级节点 1. 同级节点关系(`sibling`):拥有同一个父节点的节点 DOM 提供操作接口,用来获取这三种关系的节点。 子节点接口包括 `firstChild`(第一个子节点)和 `lastChild`(最后一个子节点)等属性, 同级节点接口包括 `nextSibling`(紧邻在后的那个同级节点)和 `previousSibling`(紧邻在前的那个同级节点)属性。 # Node 接口 ## 属性 ### Node.prototype.nodeType > nodeType 属性返回一个整数值,表示节点的类型。 _document.nodeType 是多少?_ Node 对象定义了几个常量,对应这些类型值。 ```javascript document.nodeType === Node.DOCUMENT_NODE; // true ``` 不同节点的 nodeType 属性值和对应的常量如下。 - 文档节点(`document`):9,对应常量 `Node.DOCUMENT_NODE` - 元素节点(`element`):1,对应常量 `Node.ELEMENT_NODE` - 属性节点(`attr`):2,对应常量 `Node.ATTRIBUTE_NODE` - 文本节点(`text`):3,对应常量 `Node.TEXT_NODE` - 文档片断节点(`DocumentFragment`):11,对应常量 `Node.DOCUMENT_FRAGMENT_NODE` - 文档类型节点(`DocumentType`):10,对应常量 `Node.DOCUMENT_TYPE_NODE` - 注释节点(`Comment`):8,对应常量 `Node.COMMENT_NODE` 确定节点类型时,使用 nodeType 属性是常用方法。 ```javascript var node = document.documentElement.firstChild; if (node.nodeType === Node.ELEMENT_NODE) { console.log("该节点是元素节点"); } ``` ### Node.prototype.nodeName ```html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta http-equiv="X-UA-Compatible" content="ie=edge" /> <title>Document</title> </head> <body> <div id="div1"></div> <!-- 如果改成别的... --> </body> <script> window.onload = function() { oDiv = document.getElementById("div1"); console.log("↓↓↓↓↓↓ oDiv.nodeName ↓↓↓↓↓↓"); console.log(oDiv.nodeName); }; </script> </html> ``` > `nodeName`属性返回节点的名称。 不同节点的 nodeName 属性值如下。 1. 文档节点(`document`):#document 1. 元素节点(`element`):大写的标签名 1. 属性节点(`attr`):属性的名称 1. 文本节点(`text`):#text 1. 文档片断节点(`DocumentFragment`):#document-fragment 1. 文档类型节点(`DocumentType`):文档的类型 1. 注释节点(`Comment`):#comment ### Node.prototype.nodeValue > `nodeValue` 属性返回一个字符串,表示当前节点本身的文本值,该属性可读写。 只有文本节点(text)、注释节点(comment)和属性节点(attr)有文本值,因此这三类节点的 nodeValue 可以返回结果,其他类型的节点一律返回 null。 ```html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta http-equiv="X-UA-Compatible" content="ie=edge" /> <title>Document</title> </head> <body> <hello id="div1"></hello> </body> <script> window.onload = function() { oDiv = document.getElementById("div1"); console.log("↓↓↓↓↓↓ oDiv.nodeValue ↓↓↓↓↓↓"); console.log(oDiv.nodeValue); // null }; </script> </html> ``` 文本节点例子 ```html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta http-equiv="X-UA-Compatible" content="ie=edge" /> <title>Document</title> </head> <body> <hello id="div1">hello world</hello> </body> <script> window.onload = function() { oDiv = document.getElementById("div1"); console.log("↓↓↓↓↓↓ oDiv.firstChild.nodeValue ↓↓↓↓↓↓"); oDiv.firstChild.nodeValue = "hello world !!!!!!!!"; console.log(oDiv.firstChild.nodeValue); }; </script> </html> ``` 注释节点的例子 ```html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta http-equiv="X-UA-Compatible" content="ie=edge" /> <title>Document</title> <style> div { width: 200px; height: 200px; background: red; } </style> </head> <body> <div id="div1"><!-- hello world --></div> </body> <script> window.onload = function() { oDiv = document.getElementById("div1"); console.log("↓↓↓↓↓↓ oDiv.firstChild.nodeValue ↓↓↓↓↓↓"); oDiv.firstChild.nodeValue = "hello world !!!!!!!!"; console.log(oDiv.firstChild.nodeValue); }; </script> </html> ``` 属性节点的例子 ```html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta http-equiv="X-UA-Compatible" content="ie=edge" /> <title>Document</title> <style> .div1 { width: 200px; height: 200px; background: red; } .div2 { width: 300px; height: 300px; background: green; } </style> </head> <body> <div id="div1" class="div1"></div> </body> <script> window.onload = function() { console.log( '↓↓↓↓↓↓ document.getElementById("div1").getAttributeNode("class").nodeValue ↓↓↓↓↓↓' ); console.log( document.getElementById("div1").getAttributeNode("class") .nodeValue ); document .getElementById("div1") .getAttributeNode("class").nodeValue = "div2"; }; </script> </html> ``` 同样的,也只有这三类节点可以设置 nodeValue 属性的值,其他类型的节点设置无效。 无效的例子 ```html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta http-equiv="X-UA-Compatible" content="ie=edge" /> <title>Document</title> </head> <body> <hello id="div1"></hello> </body> <script> window.onload = function() { oDiv = document.getElementById("div1"); console.log("↓↓↓↓↓↓ oDiv.nodeValue ↓↓↓↓↓↓"); console.log(oDiv.nodeValue); // null oDiv.nodeValue = "hello"; console.log(oDiv.nodeValue); }; </script> </html> ``` ```html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta http-equiv="X-UA-Compatible" content="ie=edge" /> <title>Document</title> </head> <body> <div id="d1">hello world</div> <script> window.onload = function() { var div = document.getElementById("d1"); div.nodeValue; // null console.log("↓↓↓↓↓↓ div.nodeValue ↓↓↓↓↓↓"); console.log(div.nodeValue); div.firstChild.nodeValue; // "hello world" console.log("↓↓↓↓↓↓ div.firstChild.nodeValue ↓↓↓↓↓↓"); console.log(div.firstChild.nodeValue); div.firstChild.nodeValue = "hello world!!!!!"; // "hello world" console.log("↓↓↓↓↓↓ div.firstChild.nodeValue ↓↓↓↓↓↓"); console.log(div.firstChild.nodeValue); div.nodeValue = "haha"; }; </script> </body> </html> ``` _上面代码中,div 是元素节点,nodeValue 属性返回 null。div.firstChild 是文本节点,所以可以返回文本值。_ ### Node.prototype.textContent > `textContent`属性返回当前节点和它的所有后代节点的文本内容。 _换行也会捕捉到_ ```html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta http-equiv="X-UA-Compatible" content="ie=edge" /> <title>Document</title> </head> <body> <div id="div1"> this is <span>some</span> text </div> </body> <script> window.onload = function() { console.log( '↓↓↓↓↓↓ document.getElementById("div1").textContent ↓↓↓↓↓↓' ); console.log(document.getElementById("div1").textContent); }; </script> </html> ``` 该属性是可读写的,设置该属性的值,会用一个新的文本节点,替换所有原来的子节点。 它还有一个好处,就是自动对 HTML 标签转义。这很适合用于用户提供的内容。 ```html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta http-equiv="X-UA-Compatible" content="ie=edge" /> <title>Document</title> </head> <body> <div id="div1"> this is <span>some</span> text </div> </body> <script> window.onload = function() { document.getElementById("div1").textContent = "hello world!"; document.getElementById("div1").textContent = "<h1>hello world!</h1>"; }; </script> </html> ``` 对于文本节点(text)、注释节点(comment)和属性节点(attr),textContent 属性的值与 nodeValue 属性相同。 ```html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta http-equiv="X-UA-Compatible" content="ie=edge" /> <title>Document</title> </head> <body> <div id="div1"> this is <span>some</span> text </div> </body> <script> window.onload = function() { oDiv = document.getElementById("div1"); console.log("↓↓↓↓↓↓ oDiv.firstChild.nodeValue ↓↓↓↓↓↓"); console.log(oDiv.firstChild.nodeValue); console.log("↓↓↓↓↓↓ oDiv.firstChild.textContent ↓↓↓↓↓↓"); console.log(oDiv.firstChild.textContent); }; </script> </html> ``` ```html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta http-equiv="X-UA-Compatible" content="ie=edge" /> <title>Document</title> </head> <body> <div id="div1"> <!-- this is --> <span>some</span> text </div> </body> <script> // 看看注释节点 window.onload = function() { oDiv = document.getElementById("div1"); console.log("↓↓↓↓↓↓ oDiv.firstChild.nodeValue ↓↓↓↓↓↓"); console.log(oDiv.firstChild.nodeValue); console.log("↓↓↓↓↓↓ oDiv.firstChild.textContent ↓↓↓↓↓↓"); console.log(oDiv.firstChild.textContent); }; </script> </html> ``` 属性节点的例子 ```html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta http-equiv="X-UA-Compatible" content="ie=edge" /> <title>Document</title> </head> <body> <div id="div1" class="div1"> this is <span>some</span> text </div> </body> <script> window.onload = function() { oDiv = document.getElementById("div1"); console.log(oDiv.getAttributeNode("class").nodeValue); console.log(oDiv.getAttributeNode("class").textContent); }; </script> </html> ``` 对于其他类型的节点,该属性会将每个子节点(不包括注释节点)的内容连接在一起返回。 ```html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta http-equiv="X-UA-Compatible" content="ie=edge" /> <title>Document</title> </head> <body> <div id="div1"> <!-- this is --> <span>some</span> text </div> </body> <script> // 不包括注释 window.onload = function() { oDiv = document.getElementById("div1"); console.log("↓↓↓↓↓↓ oDiv.textContent ↓↓↓↓↓↓"); console.log(oDiv.textContent); }; </script> </html> ``` 如果一个节点没有子节点,则返回空字符串。 ```html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta http-equiv="X-UA-Compatible" content="ie=edge" /> <title>Document</title> </head> <body> <div id="div1"></div> </body> <script> window.onload = function() { oDiv = document.getElementById("div1"); console.log("↓↓↓↓↓↓ oDiv.textContent ↓↓↓↓↓↓"); console.log(oDiv.textContent); console.log("↓↓↓↓↓↓ typeof(oDiv.textContent) ↓↓↓↓↓↓"); console.log(typeof oDiv.textContent); }; </script> </html> ``` 文档节点(document)和文档类型节点(doctype)的 textContent 属性为 null。 ``` document.firstChild.textContent null document.textContent null ``` 如果要读取整个文档的内容,可以使用 document.documentElement.textContent。 ### Node.prototype.baseURI `baseURI`属性返回一个字符串,表示当前网页的绝对路径。浏览器根据这个属性,计算网页上的相对路径的 URL。 该属性为只读。 ``` // 当前网页的网址为 // http://www.example.com/index.html document.baseURI // "http://www.example.com/index.html" ``` 如果无法读到网页的 URL,baseURI 属性返回 null。 该属性的值一般由当前网址的 URL(即 window.location 属性)决定 但是可以使用 HTML 的<base>标签,改变该属性的值。 ```html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta http-equiv="X-UA-Compatible" content="ie=edge" /> <base href="http://www.xujunhao.com" /> <base target="_blank" /> <title>Document</title> </head> <body></body> <script> window.onload = function() { console.log(document.baseURI); }; </script> </html> ``` 设置了以后,baseURI 属性就返回<base>标签设置的值。 ### Node.prototype.ownerDocument `Node.ownerDocument`属性返回当前节点所在的顶层文档对象,即 document 对象。 ```html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta http-equiv="X-UA-Compatible" content="ie=edge" /> <title>Document</title> </head> <body> <div id="div1"></div> </body> <script> window.onload = function() { oDiv = document.getElementById("div1"); console.log("↓↓↓↓↓↓ oDiv.ownerDocument ↓↓↓↓↓↓"); console.log(oDiv.ownerDocument); }; </script> </html> ``` document 对象本身的 `ownerDocument` 属性,返回 null。 ### Node.prototype.nextSibling `Node.nextSibling` 属性返回紧跟在当前节点后面的第一个同级节点。 如果当前节点后面没有同级节点,则返回 null。 ```html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta http-equiv="X-UA-Compatible" content="ie=edge" /> <title>Document</title> </head> <body> <div id="d1">hello</div> <div id="d2">world</div> <script> window.onload = function() { var div1 = document.getElementById("d1"); var div2 = document.getElementById("d2"); console.log(div1.nextSibling === div2); }; </script> </body> </html> ``` 注意,该属性还包括文本节点和注释节点(<!-- comment -->)。 因此如果当前节点后面有空格,该属性会返回一个文本节点,内容为空格。 ```html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta http-equiv="X-UA-Compatible" content="ie=edge" /> <title>Document</title> </head> <body> <div id="d1">hello</div> <!-- hello world --> <div id="d2">world</div> <script> window.onload = function() { console.log( '↓↓↓↓↓↓ document.getElementById("d1").nextSibling.nextSibling ↓↓↓↓↓↓' ); console.log( document.getElementById("d1").nextSibling.nextSibling ); }; </script> </body> </html> ``` nextSibling 属性可以用来遍历所有子节点。 ```html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta http-equiv="X-UA-Compatible" content="ie=edge" /> <title>Document</title> </head> <body> <div id="div1"> hello <!-- hello world --> <div id="div2">world</div> </div> <script> window.onload = function() { var oDiv = document.getElementById("div1").firstChild; while (oDiv !== null) { console.log(oDiv.nodeName); oDiv = oDiv.nextSibling; } }; </script> </body> </html> ``` 上面代码遍历 div1 节点的所有子节点 ### Node.prototype.previousSibling `previousSibling` 属性返回当前节点前面的、距离最近的一个同级节点。 如果当前节点前面没有同级节点,则返回 null。 ```html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta http-equiv="X-UA-Compatible" content="ie=edge" /> <title>Document</title> </head> <body> <div id="d1">hello</div> <div id="d2">world</div> <script> window.onload = function() { var div1 = document.getElementById("d1"); var div2 = document.getElementById("d2"); console.log(div2.previousSibling === div1); }; </script> </body> </html> ``` 上面代码中,d2.previousSibling 就是 d2 前面的同级节点 d1。 注意,该属性还包括文本节点和注释节点。 因此如果当前节点前面有空格,该属性会返回一个文本节点,内容为空格。 ### Node.prototype.parentNode `parentNode` 属性返回当前节点的父节点。 对于一个节点来说,它的父节点只可能是三种类型: 1. 元素节点(element) 2. 文档节点(document) 3. 文档片段节点(documentfragment)。 ```html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta http-equiv="X-UA-Compatible" content="ie=edge" /> <title>Document</title> </head> <body> <div id="d1">hello</div> <div id="d2">world</div> <script> window.onload = function() { var div1 = document.getElementById("d1"); var div2 = document.getElementById("d2"); console.log(div1.parentNode.nodeType); }; </script> </body> </html> ``` 关于 documentfragment ```html <!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title>菜鸟教程(runoob.com)</title> </head> <body> <ul> <li>Coffee</li> <li>Tea</li> </ul> <p id="demo"> 单击按钮更改列表项,使用createDocumentFragment方法,然后在列表的最后一个孩子添加列表项。 </p> <button onclick="myFunction()">点我</button> <script> function myFunction() { var d = document.createDocumentFragment(); d.appendChild(document.getElementsByTagName("LI")[0]); d.childNodes[0].childNodes[0].nodeValue = "Milk"; document.getElementsByTagName("UL")[0].appendChild(d); } </script> </body> </html> ``` 文档节点(document)和文档片段节点(documentfragment)的父节点都是 null。 ### Node.prototype.parentElement `parentElement` 属性返回当前节点的父元素节点。 如果当前节点没有父节点,或者父节点类型不是元素节点,则返回 null。 ```html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta http-equiv="X-UA-Compatible" content="ie=edge" /> <title>Document</title> </head> <body> <div id="div1"><span id="span1"></span></div> </body> <script> window.onload = function() { oSpan = document.getElementById("span1"); console.log("↓↓↓↓↓↓ oSpan.parentNode ↓↓↓↓↓↓"); console.log(oSpan.parentNode); console.log("↓↓↓↓↓↓ oSpan.parentNode.parentNode ↓↓↓↓↓↓"); console.log(oSpan.parentNode.parentNode); console.log("↓↓↓↓↓↓ oSpan.parentNode.parentNode.parentNode ↓↓↓↓↓↓"); console.log(oSpan.parentNode.parentNode.parentNode); console.log( "↓↓↓↓↓↓ oSpan.parentNode.parentNode.parentNode.parentNode ↓↓↓↓↓↓" ); console.log(oSpan.parentNode.parentNode.parentNode.parentNode); console.log( "↓↓↓↓↓↓ oSpan.parentNode.parentNode.parentNode.parentNode.parentNode ↓↓↓↓↓↓" ); console.log( oSpan.parentNode.parentNode.parentNode.parentNode.parentNode ); /***********************************************************************************/ console.log("↓↓↓↓↓↓ oSpan.parentElement ↓↓↓↓↓↓"); console.log(oSpan.parentElement); console.log("↓↓↓↓↓↓ oSpan.parentElement.parentElement ↓↓↓↓↓↓"); console.log(oSpan.parentElement.parentElement); console.log( "↓↓↓↓↓↓ oSpan.parentElement.parentElement.parentElement ↓↓↓↓↓↓" ); console.log(oSpan.parentElement.parentElement.parentElement); console.log( "↓↓↓↓↓↓ oSpan.parentElement.parentElement.parentElement.parentElement ↓↓↓↓↓↓" ); console.log( oSpan.parentElement.parentElement.parentElement.parentElement ); console.log( "↓↓↓↓↓↓ oSpan.parentElement.parentElement.parentElement.parentElement.parentElement ↓↓↓↓↓↓" ); console.log( oSpan.parentElement.parentElement.parentElement.parentElement .parentElement ); }; </script> </html> ``` 由于父节点只可能是三种类型: 1. 元素节点 2. 文档节点(document) 3. 文档片段节点(documentfragment)。 _`parentElement` 属性相当于把后两种父节点都排除了。_ ### Node.prototype.firstChild,Node.prototype.lastChild `firstChild` 属性返回当前节点的第一个子节点,如果当前节点没有子节点,则返回 null。 ```html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta http-equiv="X-UA-Compatible" content="ie=edge" /> <title>Document</title> </head> <body> <div id="div1"></div> </body> <script> window.onload = function() { oDiv = document.getElementById("div1"); console.log("↓↓↓↓↓↓ oDiv.firstChild ↓↓↓↓↓↓"); console.log(oDiv.firstChild); }; </script> </html> ``` 注意,firstChild 返回的除了元素节点,还可能是文本节点或注释节点。 lastChild 属性返回当前节点的最后一个子节点,如果当前节点没有子节点,则返回 null。用法与 firstChild 属性相同。 ```html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta http-equiv="X-UA-Compatible" content="ie=edge" /> <title>Document</title> </head> <body> <div id="div1"><span>span1</span></div> </body> <script> window.onload = function() { oDiv = document.getElementById("div1"); console.log("↓↓↓↓↓↓ oDiv.firstChild ↓↓↓↓↓↓"); console.log(oDiv.firstChild); console.log("↓↓↓↓↓↓ oDiv.lastChild ↓↓↓↓↓↓"); console.log(oDiv.lastChild); }; </script> </html> ``` ### Node.prototype.childNodes `childNodes` 属性返回一个类似数组的对象(NodeList 集合),成员包括当前节点的所有子节点。 ```html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta http-equiv="X-UA-Compatible" content="ie=edge" /> <title>Document</title> </head> <body> <ul> <li></li> <li></li> <li></li> <li></li> <li></li> <li></li> <li></li> <li></li> <li></li> <li></li> </ul> </body> <script> window.onload = function() { var children = document.querySelector("ul").childNodes; console.log("↓↓↓↓↓↓ children.length ↓↓↓↓↓↓"); console.log(children.length); console.log("↓↓↓↓↓↓ children ↓↓↓↓↓↓"); console.log(children); }; </script> </html> ``` 上面代码中,children 就是 ul 元素的所有子节点。 使用该属性,可以遍历某个节点的所有子节点。 ```html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta http-equiv="X-UA-Compatible" content="ie=edge" /> <title>Document</title> </head> <body> <ul> <li></li> <li></li> <li></li> <li></li> <li></li> <li></li> <li></li> <li></li> <li></li> <li></li> </ul> </body> <script> window.onload = function() { var children = document.querySelector("ul").childNodes; console.log("↓↓↓↓↓↓ children.length ↓↓↓↓↓↓"); console.log(children.length); console.log("↓↓↓↓↓↓ children ↓↓↓↓↓↓"); console.log(children); for (var i = 0; i < children.length; i++) { console.log("↓↓↓↓↓↓ children[i] ↓↓↓↓↓↓"); console.log(children[i]); } }; </script> </html> ``` 文档节点(document)就有两个子节点:文档类型节点(docType)和 HTML 根元素节点。 ```html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta http-equiv="X-UA-Compatible" content="ie=edge" /> <title>Document</title> </head> <body> <ul> <li></li> <li></li> <li></li> <li></li> <li></li> <li></li> <li></li> <li></li> <li></li> <li></li> </ul> </body> <script> window.onload = function() { var children = document.childNodes; for (var i = 0; i < children.length; i++) { console.log(children[i].nodeType); } }; </script> </html> ``` 上面代码中,文档节点的第一个子节点的类型是 10(即文档类型节点),第二个子节点的类型是 1(即元素节点)。 注意,除了元素节点,childNodes 属性的返回值还包括文本节点和注释节点。 如果当前节点不包括任何子节点,则返回一个空的 NodeList 集合。 ### Node.prototype.isConnected `isConnected` 属性返回一个布尔值,表示当前节点是否在文档之中。 ```html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta http-equiv="X-UA-Compatible" content="ie=edge" /> <title>Document</title> </head> <body> <div id="div1"><span>span1</span></div> </body> <script> window.onload = function() { var test = document.createElement("p"); console.log("↓↓↓↓↓↓ test.isConnected ↓↓↓↓↓↓"); console.log(test.isConnected); document.body.appendChild(test); console.log("↓↓↓↓↓↓ test.isConnected ↓↓↓↓↓↓"); console.log(test.isConnected); }; </script> </html> ``` 上面代码中,test 节点是脚本生成的节点,没有插入文档之前,isConnected 属性返回 false,插入之后返回 true。