ThinkChat2.0新版上线,更智能更精彩,支持会话、画图、阅读、搜索等,送10W Token,即刻开启你的AI之旅 广告
[toc] # 每日单词 # 方法 ## Node.prototype.appendChild() `appendChild` 方法接受一个节点对象作为参数,将其作为最后一个子节点,插入当前节点。 `appendChild` 返回新增的节点 ```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> <script> window.onload = function() { var p = document.createElement("p"); var returnedNode = document.body.appendChild(p); console.log(returnedNode === p); console.log(document.body.lastChild === p); }; </script> </body> </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> <script> window.onload = function() { var p = document.createElement("p"); console.log("↓↓↓↓↓↓ document.body.appendChild(p) ↓↓↓↓↓↓"); console.log(document.body.appendChild(p)); console.log(document.body.lastChild); }; </script> </body> </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> <script> window.onload = function() { var element = document .createElement("div") .appendChild(document.createElement("b")); console.log("↓↓↓↓↓↓ element ↓↓↓↓↓↓"); console.log(element); }; </script> </body> </html> ``` 如果参数节点是 DOM 已经存在的节点,appendChild 方法会将其从原来的位置,移动到新位置。 ```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>this is li0</li> <li>this is li1</li> <li>this is li2</li> <li>this is li3</li> <li>this is li4</li> <li>this is li5</li> <li>this is li6</li> <li>this is li7</li> <li>this is li8</li> <li>this is li9</li> </ul> <script> window.onload = function() { var oUl = document.getElementsByTagName("ul")[0]; var oLi = document.getElementsByTagName("li")[0]; oUl.appendChild(oLi); }; </script> </body> </html> ``` ## Node.prototype.hasChildNodes() `hasChildNodes` 方法返回一个布尔值,表示当前节点是否有子节点。 注意,子节点包括所有类型的节点,并不仅仅是元素节点。 哪怕节点只包含一个空格,`hasChildNodes` 方法也会返回 `true`。 ```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">div1</div> </body> <script> window.onload = function() { oDiv = document.getElementById("div1"); console.log(oDiv.hasChildNodes()); }; </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"><!-- div1 --></div> </body> <script> window.onload = function() { oDiv = document.getElementById("div1"); console.log(oDiv.hasChildNodes()); }; </script> </html> ``` 判断一个节点有没有子节点,有许多种方法,下面是其中的三种。 1. `node.hasChildNodes()` 2. `node.firstChild !== null` 3. `node.childNodes && node.childNodes.length > 0` ```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 !== 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> <div id="div1">11111</div> </body> <script> window.onload = function() { oDiv = document.getElementById("div1"); console.log(oDiv.childNodes && oDiv.childNodes.length > 0); }; </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">11111</div> <script> window.onload = function() { function showChild(parent, callback) { callback(parent.nodeName + ":" + parent.nodeValue); if (parent.hasChildNodes()) { for ( var node = parent.firstChild; node; node = node.nextSibling ) { showChild(node, callback); } } } showChild(document.body, console.log); }; </script> </body> </html> ``` ## Node.prototype.cloneNode() `cloneNode` 方法用于克隆一个节点。 它接受一个布尔值作为参数,表示是否同时克隆子节点。 它的返回值是一个克隆出来的新节点。 在参数为 true 的情况下,执行深复制,也就是复制节点及其整个子节点树;在参数为 false 的情况下,执行浅复制, 即只复制节点本身。 复制后返回的节点副本属于文档所有,但并没有为它指定父节点。 因此,这个节点 副本就成为了一个“孤儿”,除非通过 `appendChild`() 、 `insertBefore`() 或 `replaceChild`() 将它添加到文档中 ```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>hello world0</li> <li>hello world1</li> <li>hello world2</li> <li>hello world3</li> <li>hello world4</li> </ul> </body> <script> window.onload = function() { var deepList = document .getElementsByTagName("ul")[0] .cloneNode(true); console.log(deepList.childNodes.length); var deepList = document .getElementsByTagName("ul")[0] .cloneNode(false); console.log(deepList.childNodes.length); }; </script> </html> ``` 该方法有一些使用注意点。 1. 克隆一个节点,会拷贝该节点的所有属性,但是会丧失 `addEventListener` 方法和 `on`-属性(即 `node.onclick = fn`),添加在这个节点上的事件回调函数。 ```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> <input type="button" value="click me" /> </body> <script> document.getElementsByTagName("input")[0].onclick = function() { console.log("hello world"); }; document.body.appendChild( document.getElementsByTagName("input")[0].cloneNode() ); </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> <input type="button" value="click me" /> </body> <script> document.body.appendChild( document.getElementsByTagName("input")[0].cloneNode() ); aInput = document.getElementsByTagName("input"); for (var i = 0; i < aInput.length; i++) { aInput[i].onclick = function() { console.log("hello world"); }; } </script> </html> ``` 2. 该方法返回的节点不在文档之中,即没有任何父节点,必须使用诸如 `Node.appendChild` 这样的方法添加到文档之中。 3. 克隆一个节点之后,DOM 有可能出现两个有相同 id 属性(即 id="xxx")的网页元素,这时应该修改其中一个元素的 id 属性。 ```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-color: #ccc; margin: 20px; float: left; } </style> </head> <body> <div id="div1"></div> <div id="div2"></div> </body> <script> oDiv1 = document.getElementById("div1"); oDiv2 = document.getElementById("div2"); var cloneDiv = document.getElementById("div1").cloneNode(); // cloneDiv.getAttributeNode("id").nodeValue = "div3"; cloneDiv.setAttribute("id", "div4"); document.body.appendChild(cloneDiv); oDiv1.onclick = function() { alert("hello world"); }; </script> </html> ``` ## Node.prototype.insertBefore() `insertBefore` 方法用于将某个节点插入父节点内部的指定位置。 `var insertedNode = parentNode.insertBefore(newNode, referenceNode);` `insertBefore` 方法接受两个参数, 第一个参数是所要插入的节点 `newNode`, 第二个参数是父节点 `parentNode` 内部的一个子节点 `referenceNode`。 `newNode` 将插在 `referenceNode` 这个子节点的前面。返回值是插入的新节点 `newNode` ```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> <h1>hello world</h1> </body> <script> window.onload = function() { var p = document.createElement("p"); p.innerHTML = "hello world"; document.body.insertBefore(p, document.body.firstChild); }; </script> </html> ``` 如果 `insertBefore` 方法的第二个参数为 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> <h1>hello world</h1> </body> <script> window.onload = function() { var p = document.createElement("p"); p.innerHTML = "hello world"; document.body.insertBefore(p); }; </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> <h1>hello world</h1> </body> <script> window.onload = function() { var p = document.createElement("p"); p.innerHTML = "hello world"; document.body.insertBefore(p, null); }; </script> </html> ``` 注意,如果所要插入的节点是当前 DOM 现有的节点,则该节点将从原有的位置移除,插入新的位置。 就是, 择出来, 插回去, 个数不变 ```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> <h1>hello world</h1> <h2>hello world</h2> </body> <script> window.onload = function() { var h2 = document.getElementsByTagName("h2")[0]; document.body.insertBefore(h2, document.body.firstChild); }; </script> </html> ``` 由于不存在 insertAfter 方法,如果新节点要插在父节点的某个子节点后面,可以用 insertBefore 方法结合 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> <h1>hello world0</h1> <h2>hello world1</h2> <h3>hello world2</h3> <h4>hello world3</h4> </body> <script> window.onload = function() { var h1 = document.getElementsByTagName("h1")[0]; document.body.insertBefore( h1, document.getElementsByTagName("h3")[0].nextSibling ); }; </script> </html> ``` ## Node.prototype.removeChild() `removeChild` 方法接受一个子节点作为参数,用于从当前节点移除该子节点。返回值是移除的子节点。 ```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> <h1>hello world0</h1> <h2>hello world1</h2> <h3>hello world2</h3> <h4>hello world3</h4> </body> <script> var oh4 = document.getElementsByTagName("h4")[0]; oh4.parentNode.removeChild(oh4); </script> </html> ``` 如果参数节点不是当前节点的子节点,`removeChild` 方法将报错。 ```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> <h1>hello world0</h1> <h2>hello world1</h2> <h3>hello world2</h3> <h4>hello world3</h4> </div> <div id="div1"></div> </body> <script> var oh4 = document.getElementsByTagName("h4")[0]; var oDiv = document.getElementById("div1"); oh4.parentNode.removeChild(oDiv); </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="top"> <h1> hello world0 <span>!!!!!!!</span> </h1> <h2>hello world1</h2> <h3>hello world2</h3> <h4>hello world3</h4> </div> </body> <script> var element = document.getElementById("top"); while (element.firstChild) { element.removeChild(element.firstChild); } </script> </html> ``` 被移除的节点依然存在于内存之中,但不再是 DOM 的一部分。所以,一个节点移除以后,依然可以使用它,比如插入到另一个节点下面。 ```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="top"> <h1> hello world0 <span>!!!!!!!</span> </h1> <h2>hello world1</h2> <h3>hello world2</h3> <h4>hello world3</h4> </div> <div id="top2"></div> </body> <script> var element = document.getElementById("top"); var element2 = document.getElementById("top2"); while (element.firstChild) { var res = element.removeChild(element.firstChild); element2.appendChild(res); } </script> </html> ``` ## Node.prototype.replaceChild() `replaceChild` 方法用于将一个新的节点,替换当前节点的某一个子节点。 `var replacedNode = parentNode.replaceChild(newChild, oldChild);` 上面代码中,`replaceChild` 方法接受两个参数, 第一个参数 `newChild` 是用来替换的新节点, 第二个参数 `oldChild` 是将要替换走的子节点。 返回值是替换走的那个节点 `oldChild`。 ```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"> <h1>hello world0</h1> <h2>hello world1</h2> <h3>hello world2</h3> <h4>hello world3</h4> </div> </body> <script> var div1 = document.getElementById("div1"); var newSpan = document.createElement("span"); newSpan.textContent = "Hello World!"; div1.parentNode.replaceChild(newSpan, div1); </script> </html> ``` ## Node.prototype.contains() `contains` 方法返回一个布尔值,表示参数节点是否满足以下三个条件之一。 1. 参数节点为当前节点。 2. 参数节点为当前节点的子节点。 ```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"> <h1>hello world0</h1> <h2>hello world1</h2> <h3>hello world2</h3> <h4>hello world3</h4> </div> </body> <script> var div1 = document.getElementById("div1"); var h2 = document.getElementsByTagName("h2")[0]; console.log("↓↓↓↓↓↓ div1.contains(h2) ↓↓↓↓↓↓"); console.log(div1.contains(h2)); </script> </html> ``` 3. 参数节点为当前节点的后代节点。 ```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"> <h1>hello world0</h1> <h2>hello world1</h2> <h3>hello world2</h3> <h4>hello world3</h4> </div> </body> <script> var div1 = document.getElementById("div1"); var h2 = document.getElementsByTagName("h2")[0]; console.log("↓↓↓↓↓↓ document.body.contains(h2) ↓↓↓↓↓↓"); console.log(document.body.contains(h2)); </script> </html> ``` 注意,当前节点传入 contains 方法,返回 true。 ```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"> <h1>hello world0</h1> <h2>hello world1</h2> <h3>hello world2</h3> <h4>hello world3</h4> </div> </body> <script> var div1 = document.getElementById("div1"); console.log("↓↓↓↓↓↓ div1.contains(div1) ↓↓↓↓↓↓"); console.log(div1.contains(div1)); </script> </html> ``` ## Node.prototype.isEqualNode(),Node.prototype.isSameNode() `isEqualNode` 方法返回一个布尔值,用于检查两个节点是否相等。 所谓相等的节点,指的是两个节点的类型相同、属性相同、子节点相同。 ```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"> <h1>hello world0</h1> <h2>hello world1</h2> <h3>hello world2</h3> <h4>hello world3</h4> </div> </body> <script> var div1 = document.getElementById("div1"); var div2 = document.getElementById("div1"); console.log(div1.isEqualNode(div2)); console.log(div1.isSameNode(div2)); </script> </html> ``` `isSameNode` 方法返回一个布尔值,表示两个节点是否为同一个节点。 ```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"> <h1>hello world0</h1> <h2>hello world1</h2> <h3>hello world2</h3> <h4>hello world3</h4> </div> </body> <script> var div1 = document.createElement("div"); var div2 = document.createElement("div"); console.log(div1.isEqualNode(div2)); console.log(div1.isSameNode(div2)); </script> </html> ``` ## Node.prototype.normalize() `normailize` 方法用于清理当前节点内部的所有文本节点(text)。 它会去除空的文本节点,并且将相邻的文本节点合并成一个,也就是说不存在空的文本节点,以及相邻的文本节点。 ```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></div> <script> window.onload = function() { var wrapper = document.createElement("div"); wrapper.appendChild(document.createTextNode("Part 1 ")); wrapper.appendChild(document.createTextNode("Part 2 ")); // console.log(wrapper.childNodes.length); // console.log(wrapper.childNodes); // console.log(wrapper.firstChild); // console.log(wrapper.firstChild.nextSibling); wrapper.normalize(); console.log(wrapper.childNodes.length); console.log(wrapper.childNodes); console.log(wrapper.firstChild); }; </script> </body> </html> ``` 上面代码使用 normalize 方法之前,wrapper 节点有两个毗邻的文本子节点。使用 normalize 方法之后,两个文本子节点被合并成一个。 ```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></div> <script> window.onload = function() { var wrapper = document.createElement("div"); wrapper.appendChild(document.createTextNode("Part 1 ")); wrapper.appendChild(document.createElement("P")); wrapper.appendChild(document.createTextNode("Part 2 ")); // console.log(wrapper.childNodes.length); // console.log(wrapper.childNodes); // console.log(wrapper.firstChild); // console.log(wrapper.firstChild.nextSibling); wrapper.normalize(); console.log(wrapper.childNodes.length);//3 console.log(wrapper.childNodes);//[text,p,text] console.log(wrapper.firstChild);//text }; </script> </body> </html> ``` ## Node.prototype.getRootNode() `getRootNode` 方法返回当前节点所在文档的根节点,与 `ownerDocument` 属性的作用相同。 ```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></div> <script> window.onload = function() { var res = document.body.firstChild.getRootNode() === document; console.log(res); var res1 = document.body.firstChild.getRootNode() === document.body.firstChild.ownerDocument; console.log(res1); }; </script> </body> </html> ```