這幾天電腦有點問題,一直在弄,而且論文也逼近了也在時間弄那個 ,前面node有一個大專案,已經做完了,我現在是準備把上次複習斷下的繼續複習一直到這個專案,然後就開始vue了。
1.
首先是函式的一個進階,要明白函式也是物件,所以是可以透過new的方法來建立例項的。
然後是呼叫函式的三個方法:call可以改變this加呼叫、apply可以改變this但是傳的引數是陣列也可以呼叫、bind可以改變this傳的引數也跟第一個call一樣但是就是不會自己呼叫。
2.
今天的主打內容
閉包首先要知道嚴格模式,use srict放在區域性或者全域性作用域都可以,然後有哪些變化,變數必須宣告賦值啊、this普通函式為undefined啊、函式形參不能重名啊、函式生命必須在頂層啊等等、
高階函式:就是函式里面巢狀一個函式或者return為一個函式
然後就是閉包,什麼事閉包?
閉包就是一個能夠訪問函式區域性變數的函式,兩個注意點,一個是函式,一個是訪問區域性變數。
還是跟以前一樣傳一些我第二次做有些感想的案例吧,就不全部傳上來了。第一個是點選li列印索引號透過閉包來做
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
</ul>
<script>
/* let ul = document.querySelector('ul')
for(var i = 0; i < ul.children.length; i++) {
ul.children[i].setAttribute('data-index',i)
ul.children[i].onclick = function() {
console.log(this.getAttribute('data-index'));
}
} */
// 這裡我自己做了一下沒有用到閉包來完成,如果規定不能新增自己的屬性呢
// 這個時候你只能用i 但是當你一點選就列印出i的值那肯定是最後一個i退出迴圈的值,為什麼,因為這裡for是主棧道上的程式碼,會先執行完,
// 才會去執行事件裡面的非同步任務也就是回撥函式,所以這裡可以先用一個立即執行函式,一執行到這個i就先把這個i儲存起來有幾個迴圈就有幾個立即執行函式,
// 當你一點選就把函式里面存著的i給到他 兩個函式 兩個作用域 用到了區域性變數 所以閉包產生
let ul = document.querySelector('ul')
for(var i = 0; i < ul.children.length; i++) {
/* ul.children[i].onclick = function() {
console.log(i);
} */
(function(i) {
ul.children[i].onclick = function() {
console.log(i);
}
})(i)
}
</script>
</body>
</html>
然後是閉包算價格這個,看得出來還有點沒有完全吃透閉包的原理
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<!-- 叫車起步價13(3公里內), 之後每多一公里增加 5塊錢. 使用者輸入公里數就可以計算叫車價格
如果有擁堵情況,總價格多收取10塊錢擁堵費 -->
<script>
function getMoney() {
let total = 13
let price = 0
return {
price : function(n) {
// console.log(total, mile);
if(n > 3) {
price = total + Math.ceil(n - 3) * 5
} else {
price = total
}
return price
},
congestionPrice : function(n,congestion) {
this.price(n)
if (congestion) {
price += 10
} else {
price = total
}
return price
}
}
}
console.log(getMoney().price(1));
console.log(getMoney().congestionPrice(1,true));
console.log(getMoney().price(4));
console.log(getMoney().congestionPrice(4, true));
</script>
</body>
</html>
3.
遞迴
遞迴就是在函式內部在呼叫自身,類似於迴圈,透過return來結束。遞迴有幾個經典案例我覺得可以看一下,這次做還是熟練了好多
第一個求階乘
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
// 利用遞迴函式求1~n的階乘 1 * 2 * 3 * 4 * ..n
function getResult(n) {
if (n == 1) {
return 1
}
return n * getResult(n - 1)
}
console.log(getResult(3));
</script>
</body>
</html>
然後斐波拉起亞數列
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
/* 利用遞迴函式求斐波那契數列(兔子序列) 1、1、2、3、5、8、13、21...
// 使用者輸入一個數字 n 就可以求出 這個數字對應的兔子序列值
// 我們只需要知道使用者輸入的n 的前面兩項(n-1 n-2)就可以計算出n 對應的序列值 */
function getResult(n) {
if (n == 1 || n == 2) {
return 1
}
return getResult(n - 1) + getResult(n - 2)
}
console.log(getResult(5));
</script>
</body>
</html>
這個有一點問題,我明說我沒執行出來,但是我真的很想知道我錯在哪裡了,原理都擺在這裡是沒問題的,程式碼也沒問題,求大神指教
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
/* 我們想要做輸入id號,就可以返回的資料物件*/
var data = [{
id: 1,
name: '家電',
goods: [{
id: 11,
gname: '冰箱',
goods: [{
id: 111,
gname: '海爾'
}, {
id: 112,
gname: '美的'
},
]
}, {
id: 12,
gname: '洗衣機'
}]
}, {
id: 2,
name: '服飾'
}];
var o = {}
function getData(arr, id) {
arr.forEach(function(item) {
if (item.id == id) {
o = item
return o
} else if(item.goods && item.goods.length > 0) {
getData(item.goods, id)
}
})
}
console.log(getData(data, 1));
console.log(getData(data, 11));
</script>
</body>
</html>
說到了遞迴就順便說一下淺複製和深複製。
淺複製就是隻複製表面的一層,深層次的東西就複製引用,就是不管你改哪邊的資料,雙方都會受影響
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
// 淺複製只複製一層 更深層次只複製引用 也就是你改或者他改值雙方都受影響
var obj = {
id: 1,
name: 'andy',
msg: {
age: 18
}
}
var o = {}
for (k in obj) {
o[k] = obj[k]
}
console.log(o);
console.log('------------------')
// es6快速淺複製語法
Object.assign(obj, o)
console.log(o);
</script>
</body>
</html>
然後就是深複製,深複製就是可以單獨開闢空間,各管各的,互不影響,深複製的函式用到了遞迴,這個還是要記一下的
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
// 深複製就是更深層的資料 也會單獨開闢空間 比如陣列、函式等
var obj = {
id: 1,
name: 'andy',
msg: {
age: 18
},
color: ['pink', 'red']
}
let o = {}
function getCopy(usedCopy, useCopy) {
for (k in usedCopy) {
if (usedCopy[k] instanceof Array) {
useCopy[k] = []
getCopy(usedCopy[k], useCopy[k])
} else if (usedCopy[k] instanceof Object) {
useCopy[k] = {}
getCopy(usedCopy[k], useCopy[k])
} else {
useCopy[k] = usedCopy[k]
}
}
}
getCopy(obj, o)
console.log(o);
</script>
</body>
</html>
4.
接下來是正規表示式。
這個其實各種語法我就不多說了,參考mdn、菜鳥教程這些多得很,我說一下今天的案例有一個替換敏感字元嘛,正則裡面的規則是中文的話不用寫引號,直接寫進去就是,一個案例郵箱提取,說一下exec這個方法怎麼來多次呼叫
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
/*
將字串'小明:大神麼麼噠,正好是我想要的,我的郵箱是xiaoming@qq.com小紅:我老公最愛看這個了,我想給他一個驚喜,麼麼麼噠,
郵箱是xiaohong@sina.com我:好人一生平安,郵箱是wuyou@163.com'中所有的郵箱號碼提取出來
*/
// 注意 要使用exec進行多次匹配不僅正則要新增全域性匹配 而且還有用一個while迴圈
let str = `小明:大神麼麼噠,正好是我想要的,我的郵箱是xiaoming@qq.com小紅:我老公最愛看這個了,我想給他一個驚喜,麼麼麼噠,
郵箱是xiaohong@sina.com我:好人一生平安,郵箱是wuyou@163.com`
let reg = /\w+@\w+.[a-zA-z]+/g
var result = reg.exec(str)
while(result!== null) {
console.log(result[0]);
result = reg.exec(str)
}
</script>
</body>
</html>
正則差不多就這樣了
5.
然後是一些es6語法:let、const、解構賦值、箭頭函式。
其實我一直搞不懂let這個塊級作用域到底是限制在哪裡,我感覺作用域範圍跟var一樣哪裡都可以用,所以我後面基本都用let宣告的變數。當然我這個是錯誤思想哈,我是想以後慢慢透過例項來了解。
然後剩餘引數也就是擴充套件運算子三個點,然後就是array新增的一些方法、form可以將維陣列或者物件轉為陣列,第二個引數可以迴圈對每一個進來的值做操作,arr.find可以找滿足第一個條件的值,沒有就返回undefined,引數也是寫item\然後對應的findindex就是找
滿足第一個條件的引數的下標,還有就是查詢陣列裡面有沒有包含這個值.includes
然後就是模板字串。
string頁新增了一些方法:str.strtwith endstith看這個字元有沒有在這個字串的開頭或結尾。
.repeat可以將字元創重複n次返回一個新陣列。
最後就是set資料結構因為跟陣列相似,透過new 裡面的引數可以傳陣列,又因為自身的沒有重複值的特點所以給陣列起到一個去重的操作
然後他的一個屬性.size可以檢視set資料結構有多少值
add方法連式程式設計的形式新增資料
delete方法刪除返回的是布林值
has檢視有無返回布林值
clear清空資料結構
最後set也可以用forEach進行一個遍歷操作