網(wǎng)站模板如何編輯軟件代引流推廣公司
一、Storage
1.認(rèn)識(shí)Storage
WebStorage主要提供了一種機(jī)制,可以讓瀏覽器提供一種比cookie更直觀的key、value存儲(chǔ)方式:
localStorage
:本地存儲(chǔ),提供的是一種永久性的存儲(chǔ)方法
,在關(guān)閉掉網(wǎng)頁(yè)重新打開(kāi)時(shí),存儲(chǔ)的內(nèi)容依然保留;sessionStorage
:會(huì)話存儲(chǔ),提供的是本次會(huì)話的存儲(chǔ)
,在關(guān)閉掉會(huì)話時(shí),存儲(chǔ)的內(nèi)容會(huì)被清除;
localStorage.setItem("name", "local");
sessionStorage.setItem("name", "session");
2.localStorage和sessionStorage的區(qū)別
我們會(huì)發(fā)現(xiàn)localStorage和sessionStorage看起來(lái)非常的相似。
那么它們有什么區(qū)別呢?
- 驗(yàn)證一:關(guān)閉網(wǎng)頁(yè)后重新打開(kāi),localStorage會(huì)保留,而sessionStorage會(huì)被刪除;
- 驗(yàn)證二:在頁(yè)面內(nèi)實(shí)現(xiàn)跳轉(zhuǎn),localStorage會(huì)保留,sessionStorage也會(huì)保留;
- 驗(yàn)證三:在頁(yè)面外實(shí)現(xiàn)跳轉(zhuǎn)(打開(kāi)新的網(wǎng)頁(yè)),localStorage會(huì)保留,sessionStorage不會(huì)被保留;
3.Storage常見(jiàn)的方法和屬性
Storage有如下的屬性和方法:
屬性:
Storage.length:只讀屬性
- 返回一個(gè)整數(shù),表示存儲(chǔ)在Storage對(duì)象中的數(shù)據(jù)項(xiàng)數(shù)量;
方法:
Storage.key():該方法接受一個(gè)數(shù)值n作為參數(shù),返回存儲(chǔ)中的第n個(gè)key名稱(chēng);
Storage.getItem():該方法接受一個(gè)key作為參數(shù),并且返回key對(duì)應(yīng)的value;
Storage.setItem():該方法接受一個(gè)key和value,并且將會(huì)把key和value添加到存儲(chǔ)中。
- 如果key存儲(chǔ),則更新其對(duì)應(yīng)的值;
Storage.removeItem():該方法接受一個(gè)key作為參數(shù),并把該key從存儲(chǔ)中刪除;
Storage.clear():該方法的作用是清空存儲(chǔ)中的所有key;
const ACCESS_TOKEN = "token"console.log(localStorage.length)
// 常見(jiàn)的方法:
localStorage.setItem(ACCESS_TOKEN, "whytoken")
console.log(localStorage.getItem(ACCESS_TOKEN))// 其他方法
console.log(localStorage.key(0))
console.log(localStorage.key(1))
console.log(localStorage.removeItem("infoTab"))
localStorage.clear()
4.Storage工具封裝
class Cache {constructor(isLocal = true) {this.storage = isLocal ? localStorage: sessionStorage}setCache(key, value) {if (!value) {throw new Error("value error: value必須有值!")}if (value) {this.storage.setItem(key, JSON.stringify(value))}}getCache(key) {const result = this.storage.getItem(key)if (result) {return JSON.parse(result)}}removeCache(key) {this.storage.removeItem(key)}clear() {this.storage.clear()}
}const localCache = new Cache()
const sessionCache = new Cache(false)
<!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 src="./js/cache.js"></script><script>localCache.setCache("sno", 111)// storage本身是不能直接存儲(chǔ)對(duì)象類(lèi)型的const userInfo = {name: "abc",nickname: "def",level: 100,imgURL: "http://github.com/abc.png"}// localStorage.setItem("userInfo", JSON.stringify(userInfo))// console.log(JSON.parse(localStorage.getItem("userInfo")))sessionCache.setCache("userInfo", userInfo)console.log(sessionCache.getCache("userInfo"))</script></body>
</html>
二、正則表達(dá)式
1.什么是正則表達(dá)式?
我們先來(lái)看一下維基百科對(duì)正則表達(dá)式的解釋:
- 正則表達(dá)式(英語(yǔ):Regular Expression,常簡(jiǎn)寫(xiě)為regex、regexp或RE),又稱(chēng)正則表示式、正則表示法、規(guī)則表達(dá)式、常規(guī)表示法,是計(jì)算機(jī)科學(xué)的一個(gè)概念;
- 正則表達(dá)式使用單個(gè)字符串來(lái)描述、匹配一系列匹配某個(gè)句法規(guī)則的字符串。
- 許多程序設(shè)計(jì)語(yǔ)言都支持利用正則表達(dá)式進(jìn)行字符串操作。
簡(jiǎn)單概況:正則表達(dá)式是一種字符串匹配
利器,可以幫助我們搜索、獲取、替代字符串;
在JavaScript中,正則表達(dá)式使用RegExp
類(lèi)來(lái)創(chuàng)建,也有對(duì)應(yīng)的字面量的方式:
- 正則表達(dá)式主要由兩部分組成:模式(patterns)和修飾符(flags)
const re1 = new RegExp("hello", "i")
const re2 = /hello/i
2.正則表達(dá)式的使用方法
有了正則表達(dá)式我們要如何使用它呢?
- JavaScript中的正則表達(dá)式被用于 RegExp 的 exec 和 test 方法;
- 也包括 String 的 match、matchAll、replace、search 和 split 方法;
// 創(chuàng)建正則
const re1 = /abc/ig
const message = "fdabc123 faBC323 dfABC222 A2324aaBc"// 1.使用正則對(duì)象上的實(shí)例方法
// webpack -> loader -> test: 匹配文件名
// 正則 -> 拿到文件 -> loader操作
// 1.1.test方法: 檢測(cè)某一個(gè)字符串是否符合正則的規(guī)則
// if (re1.test(message)) {
// console.log("message符合規(guī)則")
// } else {
// console.log("message不符合規(guī)則")
// }// 1.2.exec方法: 使用正則執(zhí)行一個(gè)字符串
// const res1 = re1.exec(message)
// console.log(res1)// 2.使用字符串的方法, 傳入一個(gè)正則表達(dá)式
// 2.1. match方法:
// const result2 = message.match(re1)
// console.log(result2)// 2.2. matchAll方法
// 注意: matchAll傳入的正則修飾符必須加g
// const result3 = message.matchAll(re1)
// // console.log(result3.next())
// // console.log(result3.next())
// // console.log(result3.next())
// // console.log(result3.next())
// for (const item of result3) {
// console.log(item)
// }// 2.3. replace/replaceAll方法// 2.4. split方法
// const result4 = message.split(re1)
// console.log(result4)// 2.5. search方法
const result5 = message.search(re1)
console.log(result5)// 案例: 讓用戶(hù)輸入的賬號(hào)必須是aaaaa以上
// const inputEl = document.querySelector("input")
// const tipEl = document.querySelector(".tip")// inputEl.oninput = function() {
// const value = this.value
// if (/^a{5,8}$/.test(value)) {
// tipEl.textContent = "輸入的內(nèi)容符合規(guī)則要求"
// } else {
// tipEl.textContent = "輸入的內(nèi)容不符合規(guī)則要求, 請(qǐng)重新輸入"
// }
// }
3.修飾符flag的使用
常見(jiàn)的修飾符
flag | 含義 |
---|---|
g | 全部的,給我匹配全部的 |
i | 忽略大小寫(xiě) |
m | 多行匹配 |
需求:
- 獲取一個(gè)字符串中所有的abc
- 將一個(gè)字符串中的所有abc換成大寫(xiě)
let message = "Hello abc, abc, Abc, AAaBc"
const pattern = /abc/ig
const results = message.match(pattern)
console.log(results)message = message.replaceAll(pattern, "ABC")
console.log(message)
4.規(guī)則 – 字符類(lèi)(Character classes)
字符類(lèi)(Character classes) 是一個(gè)特殊的符號(hào),匹配特定集中的任何符號(hào)。
字符 | 含義 |
---|---|
\d(“d” 來(lái)自 “digit”) | 數(shù)字:從 0 到 9 的字符。 |
\s(“s” 來(lái)自 “space”) | 空格符號(hào):包括空格,制表符 \t,換行符 \n 和其他少數(shù)稀有字符,例如 \v,\f 和 \r。 |
\w(“w” 來(lái)自 “word”) | “單字”字符:拉丁字母或數(shù)字或下劃線 _。 |
.(點(diǎn)) | 點(diǎn) . 是一種特殊字符類(lèi),它與 “除換行符之外的任何字符” 匹配 |
反向類(lèi)(Inverse classes)
- \D 非數(shù)字:除 \d 以外的任何字符,例如字母。
- \S 非空格符號(hào):除 \s 以外的任何字符,例如字母。
- \W 非單字字符:除 \w 以外的任何字符,例如非拉丁字母或空格。
const message = "CSS2.5"
const pattern = /CSS\d(\.\d)?/i
console.log(message.match(pattern))
5.規(guī)則 – 錨點(diǎn)(Anchors)
符號(hào) ^
和符號(hào) $
在正則表達(dá)式中具有特殊的意義,它們被稱(chēng)為“錨點(diǎn)”。
- 符號(hào) ^ 匹配
文本開(kāi)頭
; - 符號(hào) $ 匹配
文本末尾
;
const message = "My name is WHY."// 字符串方法
if (message.startsWith("my")) {console.log("以my開(kāi)頭")
}
if (message.endsWith("why")) {console.log("以why結(jié)尾")
}// 正則: 錨點(diǎn)
if (/^my/i.test(message)) {console.log("以my開(kāi)頭")
}if (/why\.$/i.test(message)) {console.log("以why結(jié)尾")
}const re = /^coder$/
const info = "codaaaer"
console.log(re.test(info)) // false
詞邊界(Word boundary)
- 詞邊界
\b
是一種檢查,就像 ^ 和 $ 一樣,它會(huì)檢查字符串中的位置是否是詞邊界
。 - 詞邊界測(cè)試 \b 檢查位置的一側(cè)是否匹配 \w,而另一側(cè)則不匹配 “\w”
匹配下面字符串中的時(shí)間:
const message = "now time 22:45, number is 123.456"
const timepattern = /\b\d\d:\d\d\b/g
console.log(message.match(timepattern))
6.規(guī)則 – 轉(zhuǎn)義字符串
如果要把特殊字符作為常規(guī)字符來(lái)使用,需要對(duì)其進(jìn)行轉(zhuǎn)義
:
- 只需要在它前面加個(gè)
反斜杠
;
常見(jiàn)的需要轉(zhuǎn)義的字符:
[] \ ^ $ . | ? * + ()
- 斜杠符號(hào)
/
并不是一個(gè)特殊符號(hào),但是在字面量正則表達(dá)式中也需要轉(zhuǎn)義;
練習(xí):匹配所有以.js或者jsx結(jié)尾的文件名
const filenames = ["abc.js", "cba.java", "nba.html"]
const newNames = filenames.filter(item => {return /\.jsx?$/.test(item)
})
在webpack當(dāng)中,匹配文件名時(shí)就是以這樣的方式。
// 定義正則: 對(duì).轉(zhuǎn)義
const re = /\./ig
const message = "abc.why"const results = message.match(re)
console.log(results)// 特殊: /
// const re2 = /\//// 獲取到很多的文件名
// jsx -> js文件
const fileNames = ["abc.html", "Home.jsx", "index.html", "index.js", "util.js", "format.js"]
// 獲取所有的js的文件名(webpack)
// x?: x是0個(gè)或者1個(gè)
const jsfileRe = /\.jsx?$/
// 1.for循環(huán)做法
// const newFileNames = []
// for (const filename of fileNames) {
// if (jsfileRe.test(filename)) {
// newFileNames.push(filename)
// }
// }
// console.log(newFileNames)// 2.filter高階函數(shù)
// const newFileNames = fileNames.filter(filename => jsfileRe.test(filename))
// console.log(newFileNames)
7.集合(Sets)和范圍(Ranges)
有時(shí)候我們只要選擇多個(gè)匹配字符的其中之一就可以:
- 在方括號(hào) […] 中的幾個(gè)字符或者字符類(lèi)意味著“搜索給定的字符中的任意一個(gè)”;
集合(Sets)
- 比如說(shuō),[eao] 意味著查找在 3 個(gè)字符 ‘a(chǎn)’、‘e’ 或者
‘o’ 中的
任意一個(gè)`;
范圍(Ranges)
- 方括號(hào)也可以包含字符范圍;
- 比如說(shuō),[a-z] 會(huì)匹配從 a 到 z 范圍內(nèi)的字母,[0-5] 表示從 0 到 5 的數(shù)字;
- [0-9A-F] 表示兩個(gè)范圍:它搜索一個(gè)字符,滿(mǎn)足數(shù)字 0 到 9 或字母 A 到 F;
- \d —— 和 [0-9] 相同;
- \w —— 和 [a-zA-Z0-9_] 相同;
案例:匹配手機(jī)號(hào)碼
const phonePattern = /^1[356789]\d{9}$/
排除范圍:除了普通的范圍匹配,還有類(lèi)似 [^…] 的“排除
”范圍匹配;
// 手機(jī)號(hào)的規(guī)則: 1[3456789]033334444
const phoneStarts = ["132", "130", "110", "120", "133", "155"]
const phoneStartRe = /^1[3456789]\d/
const filterPhone = phoneStarts.filter(phone => phoneStartRe.test(phone))
console.log(filterPhone)const phoneNum = "133888855555"
const phoneRe = /^1[3-9]\d{9}$/
console.log(phoneRe.test(phoneNum))// 了解: 排除范圍
// \d -> [0-9]
// \D -> [^0-9]
8.量詞(Quantifiers)
假設(shè)我們有一個(gè)字符串 +7(903)-123-45-67,并且想要找到它包含的所有數(shù)字。
- 因?yàn)樗鼈兊臄?shù)量是不同的,所以我們需要給與數(shù)量一個(gè)范圍;
- 用來(lái)形容我們所需要的數(shù)量的詞被稱(chēng)為
量詞
( Quantifiers )。
數(shù)量 {n}
- 確切的位數(shù):{5}
- 某個(gè)范圍的位數(shù):{3,5}
縮寫(xiě):
- +:代表
一個(gè)或多個(gè)
,相當(dāng)于 {1,} - ?:代表
零個(gè)或一個(gè)
,相當(dāng)于 {0,1}。換句話說(shuō),它使得符號(hào)變得可選; - *:代表著
零個(gè)或多個(gè)
,相當(dāng)于 {0,}。也就是說(shuō),這個(gè)字符可以多次出現(xiàn)或不出現(xiàn);
案例:匹配開(kāi)始或結(jié)束標(biāo)簽
// 1.量詞的使用
const re = /a{3,5}/ig
const message = "fdaaa2fdaaaaaasf42532fdaagjkljlaaaaf"const results = message.match(re)
console.log(results)// 2.常見(jiàn)的符號(hào): +/?/*
// +: {1,}
// ?: {0,1}
// *: {0,}// 3.案例: 字符串的html元素, 匹配出來(lái)里面所有的標(biāo)簽
const htmlElement = "<div><span>哈哈哈</span><h2>我是標(biāo)題</h2></div>"
const tagRe = /<\/?[a-z][a-z0-9]*>/ig
const results2 = htmlElement.match(tagRe)
console.log(results2)
9.貪婪( Greedy)和惰性( lazy)模式
如果我們有這樣一個(gè)需求:匹配下面字符串中所有使用《》包裹的內(nèi)容
const message = "我最喜歡的兩本書(shū):《黃金時(shí)代》和《沉默的大多數(shù)》"
const results = message.match(/《.+》/g)
console.log(results)
默認(rèn)情況下的匹配規(guī)則是查找到匹配的內(nèi)容后,會(huì)繼續(xù)向后查找,一直找到最后一個(gè)匹配的內(nèi)容
- 這種匹配的方式,我們稱(chēng)之為
貪婪模式
(Greedy)
懶惰模式
中的量詞與貪婪模式中的是相反的。
- 只要獲取到對(duì)應(yīng)的內(nèi)容后,就
不再繼續(xù)向后匹配
; - 我們可以在量詞后面再加一個(gè)問(wèn)號(hào)
?
來(lái)啟用它; - 所以匹配模式變?yōu)?*? 或 +?,甚至將 ‘?’ 變?yōu)???
const message = "我最喜歡的兩本書(shū):《黃金時(shí)代》和《沉默的大多數(shù)》"
const results = message.match(/《.+?》/g)
console.log(results)
10.捕獲組(capturing group)
模式的一部分可以用括號(hào)括起來(lái) (…),這稱(chēng)為“捕獲組
(capturing group)”。
這有兩個(gè)作用:
- 它允許將匹配的一部分作為
結(jié)果數(shù)組中的單獨(dú)項(xiàng)
; - 它將括號(hào)視為一個(gè)整體;
方法 str.match(regexp),如果 regexp 沒(méi)有 g 標(biāo)志,將查找第一個(gè)匹配并將它作為一個(gè)數(shù)組返回:
- 在索引 0 處:完全匹配。
- 在索引 1 處:第一個(gè)括號(hào)的內(nèi)容。
- 在索引 2 處:第二個(gè)括號(hào)的內(nèi)容。
- …等等…
案例:匹配到HTML標(biāo)簽,并且獲取其中的內(nèi)容
const str = "<h1>title</h1>"
const result = str.match(/<(.+?)>/)
console.log(result[0])
console.log(result[1])
命名組:
- 用數(shù)字記錄組很困難。
- 對(duì)于更復(fù)雜的模式,計(jì)算括號(hào)很不方便。我們有一個(gè)更好的選擇:給括號(hào)起個(gè)名字。
- 這是通過(guò)在開(kāi)始括號(hào)之后立即放置 ? 來(lái)完成的。
const result = message.match(/(?<codermq>hel)lo/i)
非捕獲組:
- 有時(shí)我們需要括號(hào)才能正確應(yīng)用量詞,但我們不希望它們的內(nèi)容出現(xiàn)在結(jié)果中。
- 可以通過(guò)在開(kāi)頭添加 ?: 來(lái)排除組。
const result = message.match(/(?<codermq>hel)(lo)/)
or
是正則表達(dá)式中的一個(gè)術(shù)語(yǔ),實(shí)際上是一個(gè)簡(jiǎn)單的“或”。
- 在正則表達(dá)式中,它用豎線 | 表示;
- 通常會(huì)和捕獲組一起來(lái)使用,在其中表示多個(gè)值;
// 1.將捕獲組作為整體
const info = "dfabcabcfabcdfdabcabcabcljcbacballnbanba;jk;j"
const abcRe = /(abc|cba|nba){2,}/ig
console.log(info.match(abcRe))
11.封裝日期格式化函數(shù)
function formatDate(timestamp, formatString) {const date = new Date(timestamp);const obj = {"y+": date.getFullYear(),"M+": date.getMonth() + 1,"d+": date.getDate(),"h+": date.getHours(),"m+": date.getMinutes(),"s+": date.getSeconds(),"S+": date.getMilliseconds()};for (const key in obj) {if (new RegExp(`(${key})`).test(formatString)) {const value = (obj[key] + "").padStart(2, "0");formatString = formatString.replaceAll(RegExp.$1, value);}}return formatString;
}
const nowDate = Date.now();
const formatStr = formatDate(nowDate, "yyyy-MM-dd hh:mm:ss.SSS");
console.log(formatStr);