[toc]
# 每日单词
1. `ignore` 忽视
1. `Iterator` 迭代器
2. `split` 分割
3. `toggle` 开关
# Document 节点
## 概述
`document`节点对象代表整个文档,每张网页都有自己的`document`对象。`window.document`属性就指向这个对象。只要浏览器开始载入 HTML 文档,该对象就存在了,可以直接使用。
正常的网页,直接使用`document`或`window.document`。
## 属性
### 快捷方式属性
以下属性是指向文档内部的某个节点的快捷方式。
**1. document.doctype**
对于 HTML 文档来说,`document`对象一般有两个子节点。第一个子节点是`document.doctype`,指向`<DOCTYPE>`节点,即文档类型(Document Type Declaration,简写 DTD)节点。
HTML 的文档类型节点,一般写成`<!DOCTYPE html>`。如果网页没有声明 DTD,该属性返回`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>
<script>
window.onload = function() {
console.log("↓↓↓↓↓↓ document.doctype ↓↓↓↓↓↓");
console.log(document.doctype);
};
</script>
</body>
</html>
```
`document.firstChild`通常就返回这个节点。
**2. document.documentElement**
`document.documentElement`属性返回当前文档的根元素节点(root)。
它通常是`document`节点的第二个子节点,紧跟在`document.doctype`节点后面。
HTML 网页的该属性,一般是`<html>`节点。
**3. document.body,document.head**
`document.body`属性指向`<body>`节点,`document.head`属性指向`<head>`节点。
这两个属性总是存在的,如果网页源码里面省略了`<head>`或`<body>`,浏览器会自动创建。
另外,这两个属性是可写的,如果改写它们的值,相当于移除所有子节点。
_如果是浏览器自动创建, 那么 script 的位置?_
**4. document.activeElement**
`document.activeElement`属性返回获得当前焦点(focus)的 DOM 元素。通常,这个属性返回的是`<input>`、`<textarea>`、`<select>`等表单元素,如果当前没有焦点元素,返回`<body>`元素或`null`。
### 节点集合属性
以下属性返回一个`HTMLCollection`实例,表示文档内部特定元素的集合。
这些集合都是动态的,原节点有任何变化,立刻会反映在集合中。
**1. document.links**
`document.links`属性返回当前文档所有设定了`href`属性的`<a>`及`<area>`节点。
**2. document.forms**
`document.forms`属性返回所有`<form>`表单节点。
除了使用位置序号,`id`属性和`name`属性也可以用来引用表单。
```javascript
/* HTML 代码如下
<form name="foo" id="bar"></form>
*/
document.forms[0] === document.forms.foo; // true
document.forms.bar === document.forms.foo; // true
```
**3. document.images**
`document.images`属性返回页面所有`<img>`图片节点。
```javascript
var imglist = document.images;
for (var i = 0; i < imglist.length; i++) {
if (imglist[i].src === "banner.gif") {
// ...
}
}
```
上面代码在所有`img`标签中,寻找某张图片。
**4. document.scripts**
`document.scripts`属性返回所有`<script>`节点。
```javascript
var scripts = document.scripts;
if (scripts.length !== 0) {
console.log("当前网页有脚本");
}
```
### 文档静态信息属性
以下属性返回文档信息。
**(1)document.documentURI,document.URL**
`document.documentURI`属性和`document.URL`属性都返回一个字符串,表示当前文档的网址。
不同之处是它们继承自不同的接口,
`documentURI`继承自`Document`接口,可用于所有文档;
`URL`继承自`HTMLDocument`接口,只能用于 HTML 文档。
```javascript
document.URL;
// http://www.example.com/about
document.documentURI === document.URL;
// true
```
如果文档的锚点(`#anchor`)变化,这两个属性都会跟着变化。
**(2)document.domain**
`document.domain`属性返回当前文档的域名,不包含协议和接口。比如,网页的网址是`http://www.example.com:80/hello.html`,那么`domain`属性就等于`www.example.com`。
**(3)document.location**
`Location`对象是浏览器提供的原生对象,提供 URL 相关的信息和操作方法。通过`window.location`和`document.location`属性,可以拿到这个对象。
**(4)document.title**
`document.title`属性返回当前文档的标题。默认情况下,返回`<title>`节点的值。但是该属性是可写的,一旦被修改,就返回修改后的值。
```javascript
document.title = "新标题";
document.title; // "新标题"
```
## 方法
### document.open(),document.close()
`document.open`方法清除当前文档所有内容,使得文档处于可写状态,供`document.write`方法写入内容。
`document.close`方法用来关闭`document.open()`打开的文档。
```javascript
document.open();
document.write("hello world");
document.close();
```
### document.write(),document.writeln()
`document.write`方法用于向当前文档写入内容。
注意,`document.write`会当作 HTML 代码解析,不会转义。
```javascript
document.write("<p>hello world</p>");
```
上面代码中,`document.write`会将`<p>`当作 HTML 标签解释。
如果页面已经解析完成(`DOMContentLoaded`事件发生之后),再调用`write`方法,它会先调用`open`方法,擦除当前文档所有内容,然后再写入。
```javascript
document.addEventListener("DOMContentLoaded", function(event) {
document.write("<p>Hello World!</p>");
});
// 等同于
document.addEventListener("DOMContentLoaded", function(event) {
document.open();
document.write("<p>Hello World!</p>");
document.close();
});
```
如果在页面渲染过程中调用`write`方法,并不会自动调用`open`方法。(可以理解成,`open`方法已调用,但`close`方法还未调用。)
```html
<html>
<body>
hello
<script type="text/javascript">
document.write("world");
</script>
</body>
</html>
```
在浏览器打开上面网页,将会显示`hello world`。
`document.write`是 JavaScript 语言标准化之前就存在的方法,现在完全有更符合标准的方法向文档写入内容(比如对`innerHTML`属性赋值)。所以,除了某些特殊情况,应该尽量避免使用`document.write`这个方法。
`document.writeln`方法与`write`方法完全一致,除了会在输出内容的尾部添加换行符。
```javascript
document.write(1);
document.write(2);
// 12
document.writeln(1);
document.writeln(2);
// 1
// 2
//
```
注意,`writeln`方法添加的是 ASCII 码的换行符,渲染成 HTML 网页时不起作用,即在网页上显示不出换行。网页上的换行,必须显式写入`<br>`。
### document.querySelector(),document.querySelectorAll()
`document.querySelector`方法接受一个 CSS 选择器作为参数,返回匹配该选择器的元素节点。如果有多个节点满足匹配条件,则返回第一个匹配的节点。如果没有发现匹配的节点,则返回`null`。
```javascript
var el1 = document.querySelector(".myclass");
```
`document.querySelectorAll`方法与`querySelector`用法类似,区别是返回一个`NodeList`对象,包含所有匹配给定选择器的节点。
```javascript
elementList = document.querySelectorAll(".myclass");
```
这两个方法的参数,可以是逗号分隔的多个 CSS 选择器,返回匹配其中一个选择器的元素节点,这与 CSS 选择器的规则是一致的。
```javascript
var matches = document.querySelectorAll("div.note, div.alert");
```
上面代码返回`class`属性是`note`或`alert`的`div`元素。
这两个方法都支持复杂的 CSS 选择器。
```javascript
// 选中 name 属性等于 someval 的元素
document.querySelectorAll('[name="someval"]');
// 选中div元素,那些 class 含 ignore 的除外
document.querySelectorAll("DIV:not(.ignore)");
// 同时选中 div,a,script 三类元素
document.querySelectorAll("DIV, A, SCRIPT");
```
但是,它们不支持 CSS 伪元素的选择器(比如`:first-line`和`:first-letter`)和伪类的选择器(比如`:link`和`:visited`),即无法选中伪元素和伪类。
如果`querySelectorAll`方法的参数是字符串`*`,则会返回文档中的所有元素节点。另外,`querySelectorAll`的返回结果不是动态集合,不会实时反映元素节点的变化。
最后,这两个方法除了定义在`document`对象上,还定义在元素节点上,即在元素节点上也可以调用。
### document.getElementsByTagName()
`document.getElementsByTagName`方法搜索 HTML 标签名,返回符合条件的元素。它的返回值是一个类似数组对象(`HTMLCollection`实例),可以实时反映 HTML 文档的变化。如果没有任何匹配的元素,就返回一个空集。
```javascript
var res = document.getElementsByTagName("p");
res instanceof HTMLCollection; // true
```
上面代码返回当前文档的所有`p`元素节点。
HTML 标签名是大小写不敏感的,因此`getElementsByTagName`参数也是大小写不敏感的。另外,返回结果中,各个成员的顺序就是它们在文档中出现的顺序。
如果传入`*`,就可以返回文档中所有 HTML 元素。
```javascript
var allElements = document.getElementsByTagName("*");
```
注意,元素节点本身也定义了`getElementsByTagName`方法,返回该元素的后代元素中符合条件的元素。
也就是说,这个方法不仅可以在`document`对象上调用,也可以在任何元素节点上调用。
```javascript
var res = document.getElementsByTagName("p")[0];
var spans = res.getElementsByTagName("span");
```
上面代码选中第一个`p`元素内部的所有`span`元素。
### document.getElementsByClassName()
`document.getElementsByClassName`方法返回一个类似数组的对象(`HTMLCollection`实例),包括了所有`class`名字符合指定条件的元素,元素的变化实时反映在返回结果中。
```javascript
var elements = document.getElementsByClassName(names);
```
由于`class`是保留字,所以 JavaScript 一律使用`className`表示 CSS 的`class`。
参数可以是多个`class`,它们之间使用空格分隔。
```javascript
var elements = document.getElementsByClassName("foo bar");
```
上面代码返回同时具有`foo`和`bar`两个`class`的元素,`foo`和`bar`的顺序不重要。
注意,正常模式下,CSS 的`class`是大小写敏感的。(`quirks mode`下,大小写不敏感。)
与`getElementsByTagName`方法一样,`getElementsByClassName`方法不仅可以在`document`对象上调用,也可以在任何元素节点上调用。
```javascript
// 非document对象上调用
var elements = rootElement.getElementsByClassName(names);
```
### document.getElementsByName()
`document.getElementsByName`方法用于选择拥有`name`属性的 HTML 元素,返回一个类似数组的的对象(`NodeList`实例),因为`name`属性相同的元素可能不止一个。
```javascript
// 表单为 <form name="x"></form>
var forms = document.getElementsByName("x");
forms[0].tagName; // "FORM"
```
### document.getElementById()
`document.getElementById`方法返回匹配指定`id`属性的元素节点。
如果没有发现匹配的节点,则返回`null`。
```javascript
var elem = document.getElementById("para1");
```
注意,该方法的参数是大小写敏感的。比如,如果某个节点的`id`属性是`main`,那么`document.getElementById('Main')`将返回`null`。
`document.getElementById`方法与`document.querySelector`方法都能获取元素节点,不同之处是`document.querySelector`方法的参数使用 CSS 选择器语法,`document.getElementById`方法的参数是元素的`id`属性。
```javascript
document.getElementById("myElement");
document.querySelector("#myElement");
```
上面代码中,两个方法都能选中`id`为`myElement`的元素,但是`document.getElementById()`比`document.querySelector()`效率高得多。
另外,这个方法只能在`document`对象上使用,不能在其他元素节点上使用。
### document.createElement()
`document.createElement`方法用来生成元素节点,并返回该节点。
```javascript
var newDiv = document.createElement("div");
```
`createElement`方法的参数为元素的标签名,即元素节点的`tagName`属性,对于 HTML 网页大小写不敏感,即参数为`div`或`DIV`返回的是同一种节点。如果参数里面包含尖括号(即`<`和`>`)会报错。
```javascript
document.createElement("<div>");
// DOMException: The tag name provided ('<div>') is not a valid name
```
注意,`document.createElement`的参数可以是自定义的标签名。
```javascript
document.createElement("foo");
```
### document.createTextNode()
`document.createTextNode`方法用来生成文本节点(`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>
<style>
#HELLO {
width: 200px;
height: 200px;
background-color: #cccccc;
}
</style>
</head>
<body>
<div id="hello" name="hello" class="hello1 hello">222</div>
</body>
<script>
window.onload = function() {
var newDiv = document.createElement("div");
var newContent = document.createTextNode("Hello");
newDiv.appendChild(newContent);
document.body.appendChild(newDiv);
};
</script>
</html>
```
### document.createAttribute()
`document.createAttribute`方法生成一个新的属性节点(`Attr`实例),并返回它。
```javascript
var attribute = document.createAttribute(name);
```
`document.createAttribute`方法的参数`name`,是属性的名称。
```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>
</body>
<script>
window.onload = function() {
var oDiv = document.getElementsByTagName("div")[0];
var a = document.createAttribute("my_attr");
a.value = "hello";
oDiv.setAttributeNode(a);
oDiv.setAttribute("my_attr2", "hello2");
};
</script>
</html>
```
上面代码为`div1`节点,插入一个值为`newVal`的`my_attr`属性。
### document.createComment()
`document.createComment`方法生成一个新的注释节点,并返回该节点。
```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>
</body>
<script>
window.onload = function() {
var oDiv = document.getElementsByTagName("div")[0];
var oComment = document.createComment("this is a comment");
oDiv.appendChild(oComment);
};
</script>
</html>
```
`document.createComment`方法的参数是一个字符串,会成为注释节点的内容。
### document.addEventListener(),document.removeEventListener()
```javascript
// 添加事件监听函数
document.addEventListener("click", listener);
// 移除事件监听函数
document.removeEventListener("click", listener);
```
```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;
}
</style>
</head>
<body>
<div></div>
</body>
<script>
window.onload = function() {
var oDiv = document.getElementsByTagName("div")[0];
function hello() {
alert("hello world");
}
oDiv.addEventListener("click", hello);
};
</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-color: #ccc;
}
</style>
</head>
<body>
<div></div>
</body>
<script>
window.onload = function() {
var oDiv = document.getElementsByTagName("div")[0];
function hello() {
alert("hello world");
}
oDiv.addEventListener("click", hello);
oDiv.removeEventListener("click", hello);
};
</script>
</html>
```
### document.createNodeIterator()
`document.createNodeIterator`方法返回一个子节点遍历器。
```javascript
var nodeIterator = document.createNodeIterator(
document.body,
NodeFilter.SHOW_ELEMENT
);
```
上面代码返回`<body>`元素子节点的遍历器。
`document.createNodeIterator`方法第一个参数为所要遍历的根节点,第二个参数为所要遍历的节点类型,这里指定为元素节点(`NodeFilter.SHOW_ELEMENT`)。几种主要的节点类型写法如下。
- 所有节点:NodeFilter.SHOW_ALL
- 元素节点:NodeFilter.SHOW_ELEMENT
- 文本节点:NodeFilter.SHOW_TEXT
- 注释节点:NodeFilter.SHOW_COMMENT
`document.createNodeIterator`方法返回一个“遍历器”对象(`NodeFilter`实例)。该实例的`nextNode()`方法和`previousNode()`方法,可以用来遍历所有子节点。
```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>
<span>span9</span>
<div>
<span>div_span_0</span>
<span>div_span_1</span>
</div>
</div>
</body>
<script>
window.onload = function() {
var nodeIterator = document.createNodeIterator(
document.body.firstElementChild
);
var arr = [];
var currentNode;
while ((currentNode = nodeIterator.nextNode())) {
arr.push(currentNode);
}
console.log(arr);
};
</script>
</html>
```
# Element 节点
`Element`节点对象对应网页的 HTML 元素。每一个 HTML 元素,在 DOM 树上都会转化成一个`Element`节点对象(以下简称元素节点)。
元素节点的`nodeType`属性都是`1`。
```javascript
var p = document.querySelector("p");
p.nodeName; // "P"
p.nodeType; // 1
```
`Element`对象继承了`Node`接口,因此`Node`的属性和方法在`Element`对象都存在。
## 实例属性
### 元素特性的相关属性
**(1)Element.id**
`Element.id`属性返回指定元素的`id`属性,该属性可读写。
```javascript
// HTML 代码为 <p id="foo">
var p = document.querySelector("p");
p.id; // "foo"
```
注意,`id`属性的值是大小写敏感,即浏览器能正确识别`<p id="foo">`和`<p id="FOO">`这两个元素的`id`属性,但是最好不要这样命名。
**(2)Element.tagName**
`Element.tagName`属性返回指定元素的大写标签名,与`nodeName`属性的值相等。
```javascript
// HTML代码为
// <span id="myspan">Hello</span>
var span = document.getElementById("myspan");
span.id; // "myspan"
span.tagName; // "SPAN"
```
**(3)Element.lang**
`Element.lang`属性返回当前元素的语言设置。该属性可读写。
```javascript
// HTML 代码如下
// <html lang="en">
document.documentElement.lang; // "en"
```
### Element.attributes
`Element.attributes`属性返回一个类似数组的对象,成员是当前元素节点的所有属性节点
```javascript
var p = document.querySelector("p");
var attrs = p.attributes;
for (var i = attrs.length - 1; i >= 0; i--) {
console.log(attrs[i].name + "->" + attrs[i].value);
}
```
上面代码遍历`p`元素的所有属性。
### Element.className,Element.classList
`className`属性用来读写当前元素节点的`class`属性。它的值是一个字符串,每个`class`之间用空格分割。
`classList`属性返回一个类似数组的对象,当前元素节点的每个`class`就是这个对象的一个成员。
```javascript
// HTML 代码 <div class="one two three" id="myDiv"></div>
var div = document.getElementById("myDiv");
div.className;
// "one two three"
div.classList;
// {
// 0: "one"
// 1: "two"
// 2: "three"
// length: 3
// }
```
上面代码中,`className`属性返回一个空格分隔的字符串,而`classList`属性指向一个类似数组的对象,该对象的`length`属性(只读)返回当前元素的`class`数量。
`classList`对象有下列方法。
- `add()`:增加一个 class。
- `remove()`:移除一个 class。
- `contains()`:检查当前元素是否包含某个 class。
- `toggle()`:将某个 class 移入或移出当前元素。
- `item()`:返回指定索引位置的 class。
- `toString()`:将 class 的列表转为字符串。
```javascript
var div = document.getElementById("myDiv");
div.classList.add("myCssClass");
div.classList.add("foo", "bar");
div.classList.remove("myCssClass");
div.classList.toggle("myCssClass"); // 如果 myCssClass 不存在就加入,否则移除
div.classList.contains("myCssClass"); // 返回 true 或者 false
div.classList.item(0); // 返回第一个 Class
div.classList.toString();
```
下面比较一下,`className`和`classList`在添加和删除某个 class 时的写法。
```javascript
var foo = document.getElementById("foo");
// 添加class
foo.className += "bold";
foo.classList.add("bold");
// 删除class
foo.classList.remove("bold");
foo.className = foo.className.replace(/^bold$/, "");
```
`toggle`方法可以接受一个布尔值,作为第二个参数。如果为`true`,则添加该属性;如果为`false`,则去除该属性。
```javascript
el.classList.toggle("abc", boolValue);
// 等同于
if (boolValue) {
el.classList.add("abc");
} else {
el.classList.remove("abc");
}
```
### Element.innerHTML
`Element.innerHTML`属性返回一个字符串,等同于该元素包含的所有 HTML 代码。该属性可读写,常用来设置某个节点的内容。它能改写所有元素节点的内容,包括`<HTML>`和`<body>`元素。
如果将`innerHTML`属性设为空,等于删除所有它包含的所有节点。
```javascript
el.innerHTML = "";
```
上面代码等于将`el`节点变成了一个空节点,`el`原来包含的节点被全部删除。
注意,读取属性值的时候,如果文本节点包含`&`、小于号(`<`)和大于号(`>`),`innerHTML`属性会将它们转为实体形式`&`、`<`、`>`。如果想得到原文,建议使用`element.textContent`属性。
```javascript
// HTML代码如下 <p id="para"> 5 > 3 </p>
document.getElementById("para").innerHTML;
// 5 > 3
```
写入的时候,如果插入的文本包含 HTML 标签,会被解析成为节点对象插入 DOM。注意,如果文本之中含有`<script>`标签,虽然可以生成`script`节点,但是插入的代码不会执行。
```javascript
var name = "<script>alert('haha')</script>";
el.innerHTML = name;
```
上面代码将脚本插入内容,脚本并不会执行。但是,`innerHTML`还是有安全风险的。
```javascript
var name = "<img src=x onerror=alert(1)>";
el.innerHTML = name;
```
上面代码中,`alert`方法是会执行的。因此为了安全考虑,如果插入的是文本,最好用`textContent`属性代替`innerHTML`。
### Element.outerHTML
`Element.outerHTML`属性返回一个字符串,表示当前元素节点的所有 HTML 代码,包括该元素本身和所有子元素。
```javascript
// HTML 代码如下
// <div id="d"><p>Hello</p></div>
var d = document.getElementById("d");
d.outerHTML;
// '<div id="d"><p>Hello</p></div>'
```
`outerHTML`属性是可读写的,对它进行赋值,等于替换掉当前元素。
```javascript
// HTML 代码如下
// <div id="container"><div id="d">Hello</div></div>
var container = document.getElementById("container");
var d = document.getElementById("d");
container.firstChild.nodeName; // "DIV"
d.nodeName; // "DIV"
d.outerHTML = "<p>Hello</p>";
container.firstChild.nodeName; // "P"
d.nodeName; // "DIV"
```
上面代码中,变量`d`代表子节点,它的`outerHTML`属性重新赋值以后,内层的`div`元素就不存在了,被`p`元素替换了。但是,变量`d`依然指向原来的`div`元素,这表示被替换的`DIV`元素还存在于内存中。
注意,如果一个节点没有父节点,设置`outerHTML`属性会报错。
```javascript
var div = document.createElement("div");
div.outerHTML = "<p>test</p>";
// DOMException: This element has no parent node.
```
上面代码中,`div`元素没有父节点,设置`outerHTML`属性会报错。
### Element.children,Element.childElementCount
`Element.children`属性返回一个类似数组的对象(`HTMLCollection`实例),包括当前元素节点的所有子元素。如果当前元素没有子元素,则返回的对象包含零个成员。
```javascript
if (para.children.length) {
var children = para.children;
for (var i = 0; i < children.length; i++) {
// ...
}
}
```
上面代码遍历了`para`元素的所有子元素。
这个属性与`Node.childNodes`属性的区别是,它只包括元素类型的子节点,不包括其他类型的子节点。
`Element.childElementCount`属性返回当前元素节点包含的子元素节点的个数,与`Element.children.length`的值相同。
### Element.firstElementChild,Element.lastElementChild
`Element.firstElementChild`属性返回当前元素的第一个元素子节点,`Element.lastElementChild`返回最后一个元素子节点。
如果没有元素子节点,这两个属性返回`null`。
### Element.nextElementSibling,Element.previousElementSibling
`Element.nextElementSibling`属性返回当前元素节点的后一个同级元素节点,如果没有则返回`null`。
```javascript
// HTML 代码如下
// <div id="div-01">Here is div-01</div>
// <div id="div-02">Here is div-02</div>
var el = document.getElementById("div-01");
el.nextElementSibling;
// <div id="div-02">Here is div-02</div>
```
`Element.previousElementSibling`属性返回当前元素节点的前一个同级元素节点,如果没有则返回`null`。
## 实例方法
### 属性相关方法
元素节点提供六个方法,用来操作属性。
- `getAttribute()`:读取某个属性的值
- `getAttributeNames()`:返回当前元素的所有属性名
- `setAttribute()`:写入属性值
- `hasAttribute()`:某个属性是否存在
- `hasAttributes()`:当前元素是否有属性
- `removeAttribute()`:删除属性
### Element.querySelector()
`Element.querySelector`方法接受 CSS 选择器作为参数,返回父元素的第一个匹配的子元素。如果没有找到匹配的子元素,就返回`null`。
```javascript
var content = document.getElementById("content");
var el = content.querySelector("p");
```
上面代码返回`content`节点的第一个`p`元素。
`Element.querySelector`方法可以接受任何复杂的 CSS 选择器。
```javascript
document.body.querySelector("style[type='text/css'])");
```
注意,这个方法无法选中伪元素。
它可以接受多个选择器,它们之间使用逗号分隔。
```javascript
element.querySelector("div, p");
```
上面代码返回`element`的第一个`div`或`p`子元素。
需要注意的是,浏览器执行`querySelector`方法时,是先在全局范围内搜索给定的 CSS 选择器,然后过滤出哪些属于当前元素的子元素。因此,会有一些违反直觉的结果,下面是一段 HTML 代码。
```html
<div>
<blockquote id="outer">
<p>Hello</p>
<div id="inner"><p>World</p></div>
</blockquote>
</div>
```
那么,像下面这样查询的话,实际上返回的是第一个`p`元素,而不是第二个。
```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>
<div>
<blockquote id="outer">
<p>Hello</p>
<div id="inner"><p>World</p></div>
</blockquote>
</div>
<script>
window.onload = function() {
var outer = document.getElementById("outer");
console.log(outer.querySelector("div p"));
};
</script>
</html>
```
### Element.querySelectorAll()
`Element.querySelectorAll`方法接受 CSS 选择器作为参数,返回一个`NodeList`实例,包含所有匹配的子元素。
```javascript
var el = document.querySelector("#test");
var matches = el.querySelectorAll("div.highlighted > p");
```
该方法的执行机制与`querySelector`方法相同,也是先在全局范围内查找,再过滤出当前元素的子元素。因此,选择器实际上针对整个文档的。
它也可以接受多个 CSS 选择器,它们之间使用逗号分隔。如果选择器里面有伪元素的选择器,则总是返回一个空的`NodeList`实例。
### Element.getElementsByClassName()
`Element.getElementsByClassName`方法返回一个`HTMLCollection`实例,成员是当前元素节点的所有具有指定 class 的子元素节点。该方法与`document.getElementsByClassName`方法的用法类似,只是搜索范围不是整个文档,而是当前元素节点。
```javascript
element.getElementsByClassName("red test");
```
注意,该方法的参数大小写敏感。
由于`HTMLCollection`实例是一个活的集合,`document`对象的任何变化会立刻反应到实例,下面的代码不会生效。
```javascript
// HTML 代码如下
// <div id="example">
// <p class="foo"></p>
// <p class="foo"></p>
// </div>
var element = document.getElementById("example");
var matches = element.getElementsByClassName("foo");
for (var i = 0; i < matches.length; i++) {
matches[i].classList.remove("foo");
matches.item(i).classList.add("bar");
}
// 执行后,HTML 代码如下
// <div id="example">
// <p></p>
// <p class="foo bar"></p>
// </div>
```
上面代码中,`matches`集合的第一个成员,一旦被拿掉 class 里面的`foo`,就会立刻从`matches`里面消失,导致出现上面的结果。
### Element.getElementsByTagName()
`Element.getElementsByTagName`方法返回一个`HTMLCollection`实例,成员是当前节点的所有匹配指定标签名的子元素节点。该方法与`document.getElementsByClassName`方法的用法类似,只是搜索范围不是整个文档,而是当前元素节点。
```javascript
var table = document.getElementById("forecast-table");
var cells = table.getElementsByTagName("td");
```
注意,该方法的参数是大小写不敏感的。
### Element.matches()
`Element.matches`方法返回一个布尔值,表示当前元素是否匹配给定的 CSS 选择器。
```javascript
if (el.matches(".someClass")) {
console.log("Match!");
}
```
### Element.remove()
`Element.remove`方法继承自 ChildNode 接口,用于将当前元素节点从它的父节点移除。
```javascript
var el = document.getElementById("mydiv");
el.remove();
```
上面代码将`el`节点从 DOM 树里面移除。
### Element.click()
`Element.click`方法用于在当前元素上模拟一次鼠标点击,相当于触发了`click`事件。
# 属性的操作
HTML 元素包括标签名和若干个键值对,这个键值对就称为“属性”(attribute)。
```html
<a id="test" href="http://www.example.com">链接</a>
```
上面代码中,`a`元素包括两个属性:`id`属性和`href`属性。
属性本身是一个对象(`Attr`对象),一般都是通过元素节点对象(`HTMlElement`对象)来操作属性。
## Element.attributes 属性
元素对象有一个`attributes`属性,返回一个类似数组的动态对象,成员是该元素标签的所有属性节点对象,属性的实时变化都会反映在这个节点对象上。其他类型的节点对象,虽然也有`attributes`属性,但返回的都是`null`,因此可以把这个属性视为元素对象独有的。
单个属性可以通过序号引用,也可以通过属性名引用。
```javascript
// HTML 代码如下
// <body bgcolor="yellow" onload="">
document.body.attributes[0];
document.body.attributes.bgcolor;
document.body.attributes["ONLOAD"];
```
注意,上面代码的三种方法,返回的都是属性节点对象,而不是属性值。
属性节点对象有`name`和`value`属性,对应该属性的属性名和属性值,等同于`nodeName`属性和`nodeValue`属性。
```javascript
// HTML代码为
// <div id="mydiv">
var n = document.getElementById("mydiv");
n.attributes[0].name; // "id"
n.attributes[0].nodeName; // "id"
n.attributes[0].value; // "mydiv"
n.attributes[0].nodeValue; // "mydiv"
```
## 属性操作的标准方法
### 概述
元素节点提供六个方法,用来操作属性。
- `getAttribute()`
- `getAttributeNames()`
- `setAttribute()`
- `hasAttribute()`
- `hasAttributes()`
- `removeAttribute()`
这有几点注意。
(1)适用性
这六个方法对所有属性(包括用户自定义的属性)都适用。
(2)返回值
`getAttribute()`只返回字符串,不会返回其他类型的值。
(3)属性名
这些方法只接受属性的标准名称,不用改写保留字,比如`for`和`class`都可以直接使用。另外,这些方法对于属性名是大小写不敏感的。
```javascript
var image = document.images[0];
image.setAttribute("class", "myImage");
```
上面代码中,`setAttribute`方法直接使用`class`作为属性名,不用写成`className`。
### Element.getAttribute()
`Element.getAttribute`方法返回当前元素节点的指定属性。如果指定属性不存在,则返回`null`。
```javascript
// HTML 代码为
// <div id="div1" align="left">
var div = document.getElementById("div1");
div.getAttribute("align"); // "left"
```
### Element.getAttributeNames()
`Element.getAttributeNames()`返回一个数组,成员是当前元素的所有属性的名字。如果当前元素没有任何属性,则返回一个空数组。使用`Element.attributes`属性,也可以拿到同样的结果,唯一的区别是它返回的是类似数组的对象。
```javascript
var mydiv = document.getElementById("mydiv");
mydiv.getAttributeNames().forEach(function(key) {
var value = mydiv.getAttribute(key);
console.log(key, value);
});
```
上面代码用于遍历某个节点的所有属性。
### Element.setAttribute()
`Element.setAttribute`方法用于为当前元素节点新增属性。如果同名属性已存在,则相当于编辑已存在的属性。该方法没有返回值。
```javascript
// HTML 代码为
// <button>Hello World</button>
var b = document.querySelector("button");
b.setAttribute("name", "myButton");
b.setAttribute("disabled", true);
```
上面代码中,`button`元素的`name`属性被设成`myButton`,`disabled`属性被设成`true`。
这里有两个地方需要注意,首先,属性值总是字符串,其他类型的值会自动转成字符串,比如布尔值`true`就会变成字符串`true`;其次,上例的`disable`属性是一个布尔属性,对于`<button>`元素来说,这个属性不需要属性值,只要设置了就总是会生效,因此`setAttribute`方法里面可以将`disabled`属性设成任意值。
### Element.hasAttribute()
`Element.hasAttribute`方法返回一个布尔值,表示当前元素节点是否包含指定属性。
```javascript
var d = document.getElementById("div1");
if (d.hasAttribute("align")) {
d.setAttribute("align", "center");
}
```
上面代码检查`div`节点是否含有`align`属性。如果有,则设置为居中对齐。
### Element.hasAttributes()
`Element.hasAttributes`方法返回一个布尔值,表示当前元素是否有属性,如果没有任何属性,就返回`false`,否则返回`true`。
```javascript
var foo = document.getElementById("foo");
foo.hasAttributes(); // true
```
### Element.removeAttribute()
`Element.removeAttribute`方法移除指定属性。该方法没有返回值。
```javascript
// HTML 代码为
// <div id="div1" align="left" width="200px">
document.getElementById("div1").removeAttribute("align");
// 现在的HTML代码为
// <div id="div1" width="200px">
```
- 每日单词
- JavaScript 入门
- JavaScript 基础
- JavaScript 基础回顾
- JavaScript 函数
- 匿名函数,多维数组,数据类型转换
- JavaScript 类型转换, 变量作用域
- js 运算符(一)
- js 运算符(二)
- js 流程控制语句
- JavaScript 扫盲日
- JavaScript 牛刀小试(一)
- JavaScript 牛刀小试(二)
- JavaScript 再谈函数
- JavaScript-BOM
- JavaScript-定时器(一)
- JavaScript-定时器(二)
- 番外-轮播图源码
- JavaScript 轮播图和 DOM 简介
- JavaScript-DOM 基础-NODE 接口-属性
- JavaScript-DOM 基础-NODE 接口-方法
- NodeList-接口-HTMLCollection-接口
- Document 节点
- CSS 复习与扩展(一)
- CSS 复习与扩展(二)
- 走进 jQuery 的世界
- 使用 jquery
- 使用 jquery-2
- jquery 中高级
- jquery 备忘清单-1
- jquery 备忘清单-2
- 聊聊 json
- jquery 备忘清单-3