[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