>### A.今天學什么?
#### 1.定時器timer
- ##### 1.1 setTimeout --> 超時調用
- 語法:setTimeout(func,time); 時間單位為毫秒,間隔一段時間觸發函數,只觸發一次
- ##### 1.2 setInterval -- > 重復調用
- 語法:setInterval(func,time); 每間隔一段時間觸發
```
// body
<body>
<script>
// setTimeout --> 超時調用
// 語法
// setTimeout(func,time) 時間單位為毫秒
// 間隔一段時間觸發函數,只觸發一次
setTimeout(function () {
alert("測試");
},2000);
/*
setInterval -- > 重復調用
語法
setInterval(func,time);
每間隔一段時間觸發*/
setInterval(function () {
alert("測試")
},2000)
</script>
</body>
```
- ##### 1.3 使用setTimeout實現setInterval
- 核心:遞歸調用
```
// body
<body>
<script>
// 使用setTimeout實現setInterval
// 相當于無限遞歸
function go() {
alert("hello world");
setTimeout(go,1000);
}
go();
</script>
</body>
```
#### 2.制作一個input框和按鈕,輸入后,將內容放入ul內
- ##### 2.1使用方法
- 獲取元素對象
- onclick事件
- 對象.value屬性 ---> 輸入內容
- 創建元素對象
- 對象.innerHTML屬性 ---> 標簽內內容
```
// body
<body>
<div>
<input type="text" id="txt" />
<button id="add">添加</button>
</div>
<ul id="parent">
</ul>
<script>
var txt = document.getElementById("txt");
var add = document.getElementById("add");
var parent = document.getElementById("parent");
add.onclick = function () {
var value = txt.value;
// 提交后,將其清空
txt.value = ""; // value是輸入框里的值
var li = document.createElement("li");
li.innerHTML = value; // innerHTML是元素內的內容
console.log(li);
parent.appendChild(li);
}
</script>
</body>
```
#### 3.DOM獲取元素父節點
- ##### 3.1方法介紹
- node.parentNode --> 獲取父元素(親爹~),比如 body>ul>li(這里的>代表上下父子關系),li.parentNode,不會獲取body,只會獲取ul。
```
// body
<body>
<div class="parent">
<p class="child">hello world</p>
</div>
<script>
// node.parentNode --> 獲取父元素(親爹~)
var p = document.getElementsByClassName("child")[0];
var parent = p.parentNode;
console.log(parent);
</script>
</body>
```
- ##### 3.2實例:點擊刪除,刪掉父節點
- 利用for循環給a標簽加上onclick事件
- 注意a標簽內href加#,或者onclick事件最后return false;終止a標簽的默認跳轉。否則會造成,刪除又恢復BUG
```
// body
<body>
<ul>
<li>小米<a href="#">刪除</a></li>
<li>華為<a href="#">刪除</a></li>
<li>蘋果<a href="#">刪除</a></li>
</ul>
<script>
var shows = document.getElementsByTagName("a");
for (var i = 0;i <shows.length;i++){
shows[i].onclick = function () {
// this指正在執行事件的當前對象
this.parentNode.style.display = "none";
// 阻止a標簽的默認跳轉事件,否則會發生
// 刪掉又恢復了的情況
// 或者給a標簽 href 給一個 #,表示當前頁面,不會跳轉。
return false;
}
}
</script>
</body>
```
#### 4.獲取子節點
- ##### 4.1 childNodes --> 獲取所有類型的子節點
- childNodes --> 獲取所有類型的子節點,```
// <ul id="parent">
// <li>```
// 之間的換行符也會被當成一個文本節點
- ##### 4.2 children --> 獲取所有的元素子節點,IE9以后
- 只會獲取元素節點,不會獲取文本節點。IE9之后貌似才支持,所以不要用IE~~
- ##### 4.3 獲取第一個、最后一個子節點
- firstChild --> 獲取第一個子節點
- lastChild --> 獲取最后一個子節點
- ##### 4.4 獲取第一個、最后一個元素子節點
- firstElementChild --> 獲取第一個元素子節點
- lastElementChild --> 獲取最后一個元素子節點
```
// body
<body>
<ul id="parent">
<li>1</li>
<li>2</li>
<li>3</li>
</ul>
<script>
// childNodes --> 獲取所有類型的子節點,
// <ul id="parent">
// <li>
// 之間的換行符也會被當成一個文本節點
var parent = document.getElementById("parent");
var childNodes = parent.childNodes;
console.log("parent的childNodes長度為"+childNodes.length);
// nodeType值為1時,是元素節點
// 文本節點不能設置背景顏色,會報錯,所以需要過濾
for(var i = 0;i < childNodes.length;i++){
if(childNodes[i].nodeType === 1){
childNodes[i].style.backgroundColor = "red";
}
}
// children --> 獲取所有的元素子節點,IE9以后
var childs = parent.children;
console.log("parent的children長度為"+childs.length);
// firstChild --> 獲取第一個子節點
// lastChild --> 獲取最后一個子節點
var fc = parent.firstChild;
console.log(fc);
var lc = parent.lastChild;
console.log(lc);
// firstElementChild --> 獲取第一個元素子節點
// lastElementChild --> 獲取最后一個元素子節點
var fec = parent.firstElementChild;
console.log(fec);
var lec = parent.lastElementChild;
console.log(lec);
</script>
</body>
```
#### 5.獲取兄弟節點
- ##### 5.1獲取兄弟節點--所有類型的節點
- node.previousSibling -->獲取前面的兄弟節點
- node.nextSibling --> 獲取后面的兄弟節點
- ##### 5.2獲取兄弟元素節點
- node.previousElementSibling --> 獲取前面的兄弟元素節點
- node.nextElementSibling --> 獲取后面的兄弟元素節點
```
// body
<body>
<div>
<p>hello world 01</p>
<p id="test">hello my friend 02</p>
<p>hello chunjue 03</p>
</div>
<script>
/*node.previousSibling -->獲取前面的兄弟節點
node.nextSibling --> 獲取后面的兄弟節點*/
var test = document.getElementById("test");
var pSibling = test.previousSibling;
var nSibling = test.nextSibling;
console.log("test.previousSibling"+pSibling);
console.log("test.nextSibling"+nSibling);
/*node.previousElementSibling --> 獲取前面的兄弟元素節點
node.nextElementSibling --> 獲取后面的兄弟元素節點*/
var peSibling = test.previousElementSibling;
var neSibling = test.nextElementSibling;
</script>
</body>
```
#### 6.offset屬性
- ##### 6.1 特點
- 只讀,無法更改
- ##### 6.2 獲取元素偏移量
- element.offsetLeft --> 獲取元素的左偏移量
- element.offsetTop --> 獲取元素的上偏移量
- ##### 6.3 獲取元素的寬高
- element.offsetWidth --> 獲取元素的寬度
- element.offsetHeight --> 獲取元素的高度
```
// css
<style>
*{margin: 0;padding: 0}
div{
width: 100px;
height: 100px;
background-color: red;
margin: 100px;
position: absolute;
left: 100px;
padding: 20px;
border: 10px solid #333;
}
</style>
// body
<body>
<div id="test">
</div>
<script>
// 特點:只讀屬性,無法修改
var test = document.getElementById("test");
// element.offsetLeft --> 獲取元素的左偏移量
// element.offsetTop --> 獲取元素的上偏移量
var offL = test.offsetLeft;
var offT = test.offsetTop;
// test.offsetLeft = "1000px"; 只讀屬性,無法修改
console.log("test.offsetLeft"+offL);
console.log("test.offsetTop"+offT);
// element.offsetWidth --> 獲取元素的寬度
// element.offsetHeight --> 獲取元素的高度
var offW = test.offsetWidth;
var offH = test.offsetHeight;
// test.offsetWidth = "500px"; 只讀屬性,無法修改
console.log("test.offsetWidth"+offW);
console.log("test.offsetHeight"+offH);
</script>
</body>
```
#### 7.屬性的操作--Attribute
- ##### 7.1 設置屬性值
- 設置屬性值 --> element.setAttribute("屬性名", "屬性值");
- 使用設置屬性值的方式來設置樣式值
- test.setAttribute("style","color:red"); style也是屬性,內聯樣式
- ##### 7.2 獲取屬性值
- 獲取屬性值 --> element.getAttribute("屬性名");
- var cValue = test.getAttribute("class");
- ##### 7.3 移除屬性值
- 移除屬性值 --> removeAttribute("屬性名");
- test.removeAttribute("class");
```
// body
<body>
<p id="test" class="one">hello world</p>
<script>
// 設置屬性值 --> element.setAttribute("屬性名", "屬性值");
// 使用設置屬性值的方式來設置樣式值
var test = document.getElementById("test");
test.setAttribute("style","color:red");
// 獲取屬性值 --> element.getAttribute("屬性名");
var cValue = test.getAttribute("class");
console.log(cValue);
// 將p標簽的class設置為two
test.setAttribute("class","two");
console.log(test.getAttribute("class"));
// 移除屬性值 --> removeAttribute("屬性名");
test.removeAttribute("class");
</script>
</body>
```
- 7.4 利用設置屬性方法,設置鼠標懸停提示
- title屬性,鼠標懸停提示
```
// body
<body>
<p id="test">hello chunjue</p>
<script>
var test = document.getElementById("test");
// title屬性,鼠標放上去會出現的那種提示
test.setAttribute("title","title");
</script>
</body>
```
#### 8.窗口寬高
- ##### 8.1 瀏覽器的寬高 -- 由窗口大小決定
- window.innerWidth; --> 瀏覽器寬度
- window.innerHeight; --> 瀏覽器高度
- ##### 8.2 文檔元素的寬高 -- 和瀏覽器一樣(目前來看
- document.documentElement.clientWidth; --> 文檔元素寬度
- document.documentElement.clientHeight; --> 文檔元素高度
- ##### 8.3 對象body的寬高 -- 由內部元素寬高決定
- document.body.clientWidth; --> 對象body寬度
- document.body.clientHeight; --> 對象body高度
- ##### 8.4 獲取頁面內容的寬高
- 如果瀏覽器顯示內容小于內部元素寬高,則顯示元素的寬高;如果大于內部元素的寬高,則顯示瀏覽器寬高,不同瀏覽器顯示不一樣,不必糾結
- document.documentElement.scrollWidth; --> 頁面內容寬度
- document.documentElement.scrollHeight; --> 頁面內容高度
```
// css
<style>
*{margin: 0;padding: 0}
#test{
height: 300px;
background-color: red;
}
</style>
// body
<body>
<div id="test"></div>
<script>
// 瀏覽器的寬高 -- 由窗口大小決定
// window.innerWidth --> 瀏覽器寬度
// window.innerHeight --> 瀏覽器高度
var windowWidth = window.innerWidth;
var windowHeight = window.innerHeight;
console.log("瀏覽器寬度為"+windowWidth);
console.log("瀏覽器高度為"+windowHeight);
// 文檔元素的寬高 -- 和瀏覽器一樣
var dw = document.documentElement.clientWidth;
var dh = document.documentElement.clientHeight;
console.log("文檔元素的寬度為"+dw);
console.log("文檔元素的高度為"+dh);
// 對象body的寬高 -- 由內部元素寬高決定
var bw = document.body.clientWidth;
var bh = document.body.clientHeight;
console.log("body的寬度"+bw);
console.log("body的高度"+bh);
// 獲取頁面內容的寬高 -- 如果瀏覽器顯示內容小于內部元素寬高,則顯示元素的寬高
// 如果大于內部元素的寬高,則顯示瀏覽器寬高,不同瀏覽器顯示不一樣,不必糾結
var dsw = document.documentElement.scrollWidth;
var dsh = document.documentElement.scrollHeight;
console.log("頁面內容的寬為"+dsw);
console.log("頁面內容的高位"+dsh);
</script>
</body>
```
#### 9.文檔碎片
- ##### 9.1優點:提高渲染效率
- document.createDocumentFragment(); --> 創建文檔碎片
- 是一個脫離文檔流的碎片,相當于一個緩沖區
- 相當于一個緩沖區
```
// body
<body>
<ul id="parent">
</ul>
<button id="btn">btn</button>
<script>
// document.createDocumentFragment(); --> 文檔碎片,優點:提高渲染效率
var btn = document.getElementById("btn");
var parent = document.getElementById("parent");
// 脫離文檔流的碎片,相當于一個緩沖區
var frame = document.createDocumentFragment();
btn.onclick = function () {
for (var i = 0;i < 10;i++){
var li = document.createElement("li");
// 利用fragment緩沖,可以提升一定性能。
frame.appendChild(li);
}
parent.appendChild(frame);
}
</script>
</body>
```
#### 10.表格屬性
- ##### 10.1表格屬性與獲取方法
- table.tHead --> 獲取表格的標題部分
- table.tBodies --> 獲取表格的主體部分,得到的是一個數組,因為表格可能有多個tbody
- tbody.rows --> 獲取tbody每一行tr,得到的也是一個數組
- rows[n].cells[n] --> 獲取第n行tr的第n個單元格td
- ##### 10.2利用js表格屬性完成以下要求
- 1.標題的背景色變為 #eee
- 2.tbody下奇數行為 #ff2d51 偶數行為 #44cef6
```
// css
<style>
table,td,th{
border: 1px solid #333;
}
table{
width: 500px;
border-collapse: collapse;
line-height: 50px;
text-align: center;
}
</style>
// body
<body>
<table id="table">
<thead>
<tr>
<th>商城</th>
<th>手機</th>
</tr>
</thead>
<tbody>
<tr>
<td>京東商城</td>
<td>蘋果手機</td>
</tr>
<tr>
<td>天貓</td>
<td>華為手機</td>
</tr>
<tr>
<td>拼多多</td>
<td>魅族手機</td>
</tr>
<tr>
<td>小米商城</td>
<td>小米</td>
</tr>
</tbody>
</table>
<script>
/*1.標題的背景色變為 #eee
2.tbody下奇數行為 #ff2d51 偶數行為 #44cef6*/
var table = document.getElementById("table");
// table.tHead --> 獲取表格的標題部分
var thead = table.tHead;
// table.tBodies --> 獲取表格的主體部分,得到的是一個數組,因為表格可能有多個tbody
var tbody = table.tBodies[0];
// tbody.rows --> 獲取tbody每一行tr,得到的也是一個數組
var rows = tbody.rows;
// rows[n].cells[n] --> 獲取第n行tr的第n個單元格td
var firstCell = rows[0].cells[0];
console.log(thead);
thead.style.backgroundColor = "#eee";
for (var i = 0;i < rows.length;i++){
if(i%2 === 0){
rows[i].style.backgroundColor = "#ff2d51";
}
else{
rows[i].style.backgroundColor = "#44cef6";
}
}
firstCell.innerHTML = "銀泰百貨";
</script>
</body>
```
- ##### 10.3動態添加表格主體內容
- 標題 -- 品牌,價格
- 兩個input框分別輸入品牌與價格,要求按下按鈕,能添加到表格內
```
// css
<style>
table{
border: 1px solid #333;
width: 500px;
line-height: 50px;
border-collapse: collapse;
text-align: center;
margin-top: 30px;
}
th,td{
border: 1px solid #333;
}
</style>
// body
<body>
<div>
手機品牌<input type="text" id="phone" />
價格<input type="text" id="price" />
<button id="btn">添加</button>
</div>
<table id="table">
<thead>
<tr>
<th width="60%">品牌</th>
<th>價格</th>
</tr>
</thead>
<tbody>
<tr>
<td>蘋果5</td>
<td>3000</td>
</tr>
</tbody>
</table>
<script>
var btn = document.getElementById("btn");
var phone = document.getElementById("phone");
var price = document.getElementById("price");
var tbody = document.getElementById("table").tBodies[0];
btn.onclick = function ( ) {
var tr = document.createElement("tr");
var td = document.createElement("td");
td.innerHTML = phone.value;
tr.appendChild(td);
var td1 = document.createElement("td");
td1.innerHTML = price.value;
tr.appendChild(td1);
console.log(tr);
tbody.appendChild(tr);
}
</script>
</body>
```
#### 11.函數function
- ##### 11.1定義函數的三種方法
- 1.直接定義函數 --> function funcName(args){方法體},可以在函數定義前就調用,但是不推薦
- 2.變量聲明定義函數 --> var funcName = function(args){方法體},由于js的聲明提前,不能在函數定義前調用,不推薦
- 3.構造函數的方式聲明 --> var funcName = new Function("args","方法體"); 第一個參數為參數,第二個為函數表達式--更加不推薦
```
// body
<body>
<script>
// 1.直接定義函數
function go() {
console.log("hello world");
}
go(); // 在函數定義前面調用也可以,但是不推薦,還是按順序式調用
// 2.變量聲明定義函數 -- 會造成聲明提前,這樣的話就不能在定義函數之前調用
var one = function () {
console.log("one");
};
one();
// 3.構造函數的方式聲明 -- 第一個參數為參數,第二個為函數表達式--更加不推薦
var two = new Function("two","console.log(two)");
two("aaa");
</script>
</body>
```
- ##### 11.2 ES6新的定義函數方法--箭頭函數
- 定義方法:var funcName = (args)=>{方法體},ES6的箭頭函數,ES5不支持
```
// body
<body>
<script>
var one = function () {
console.log("one")
};
// ES6箭頭函數
var go = ()=>{
console.log("hello ES6");
}
go();
// 創建一個對象,其中有2個函數。
var obj = {
say:function () {
console.log("say");
},eat:()=>{
console.log("eat");
}
}
obj.eat();
</script>
</body>
```
- ##### 11.3 js函數的傳參
- javaScript不同于java,定義函數參數列表有2個參數,但是執行函數時,甚至可以一個參數都不傳,因此,javaScript不像java那樣支持函數的重載
- 如果想實現類似函數重載的效果,需要用到javaScript特有的,函數中存在的arguments對象,其中存儲了調用函數時傳入的參數,然后根據其長度判斷執行不同的方法體。
- 函數內部有一個arguments對象來管理函數傳入的參數,然后可以根據arguments的長度來執行方法體
```
// body
<body>
<script>
// js中函數傳不定參
function go(a,b) {
console.log(a);
console.log(b);
}
go(); // 不會報錯,輸出NaN
// 所以js中一般函數不能重載,后面的重名函數會覆蓋前面的重名函數
// js中如何實現重載 使用arguments對象
// 函數內部有一個arguments對象來管理函數傳入的參數,然后可以根據arguments的長度來執行方法體
function test() {
console.log(arguments);
console.log(arguments.length);
}
// 做一個重載函數的例子 -- 其實就是根據傳入參數長度不同進入不同的if判斷
function testFunc() {
if (arguments.length === 1){
console.log(arguments[0]);
}
else if (arguments.length === 2){
console.log(arguments[1]);
}
else{
console.log("hello chunjue");
}
}
</script>
</body>
```
#### 14.js基本類型和引用類型的區別
- ##### 14.1 javaScript這兩種變量類型的區別,與java差不多
- 1.基本類型只傳值
- 2.引用類型既傳值也傳址,兩者指向同一個地址
```
// body
<body>
<script>
// 1.基本類型只傳值
// 2.引用類型既傳值也傳址,兩者指向同一個地址
var a = 10;
var b = a;
a = 15;
console.log(b); // 10
// 這時候,b還是10,不會隨著a的改變而改變,因為基本類型都在棧里面,占據固定內存大小,是直接使用的。
// var arr1 = arr的時候,是讓arr1指向了arr指向的地址,
// 如果修改該地址的引用類型變量,那么指向該地址的變量的值都會改變
var arr = [1,2,3];
var arr1 = arr;
arr[arr.length] = 4;
console.log(arr1); // [1,2,3,4]
// 對象也同理
var obj = {name:"依然"};
var yiran = obj;
obj.age = 21;
console.log(yiran.age);
</script>
</body>
```