這幾天電腦有點問題,一直在弄,而且論文也逼近了也在時間弄那個 ,前面node有一個大項目,已經做完了,我現在是準備把上次複習斷下的繼續複習一直到這個項目,然後就開始vue了。 1. 首先是函數的一個進階,要明白函數也是對象,所以是可以通過new的方法來創建實例的。 然後是調用函數的三個方法:call ...
這幾天電腦有點問題,一直在弄,而且論文也逼近了也在時間弄那個 ,前面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> /* 將字元串'小明:大神麽麽噠,正好是我想要的,我的郵箱是[email protected]小紅:我老公最愛看這個了,我想給他一個驚喜,麽麽麽噠, 郵箱是[email protected]我:好人一生平安,郵箱是[email protected]'中所有的郵箱號碼提取出來 */ // 註意 要使用exec進行多次匹配不僅正則要添加全局匹配 而且還有用一個while迴圈 let str = `小明:大神麽麽噠,正好是我想要的,我的郵箱是[email protected]小紅:我老公最愛看這個了,我想給他一個驚喜,麽麽麽噠, 郵箱是[email protected]我:好人一生平安,郵箱是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進行一個遍歷操作