20 初识正则表达式
<body>
<form action="">
<input type="text" required id="mytext">
<input type="email">
<input type="submit" value="submit">
</form>
<script>
//正则表达式
// js复杂类型
//1. 字面量 //
var reg = /abc/ //检测一个字符串里是不是包含“abc”
console.log(reg)
//2. 内置构造函数
var reg2 = new RegExp("abc")
console.log(reg2)
mytext.onblur = function(){
console.log(mytext.value)
console.log(reg.test(mytext.value))
}
</script>
</body>
21 元字符
21-1 基本元字符
1. \d 一位数字(0-9)
2. \D 包含一位非数字
3. \s 1位空白 (空格 缩进 换行\n)
4. \S 1位 非空白
5. \w 字母 数字 下划线
6. \W 非字幕数字下划线
7. . 任意内容 (换行不算)
8 . \转义字符
<script>
// 1 \d 一位数字(0-9)
// var reg = /\d/ //一位数字
// console.log(reg.test("abc")) //false
// console.log(reg.test("123")) //true
// console.log(reg.test("1")) //true
// var reg = /\d\d/ //两位数字
// console.log(reg.test("1")) //false
// 2 \D 包含一位非数字
// var reg = /\D/ //一位
// console.log(reg.test("123a")) //true
// console.log(reg.test("123")) //false
// console.log(reg.test("1")) //false
// var reg = /\D\D/ //两位
// var reg = /\Dk\D/ //一位非数字k一位非数字
// console.log(reg.test("aka")) //true
// console.log(reg.test("aba")) //false
// 3. \s 1位空白 (空格 缩进 换行\n)
// var reg = /\s/
// console.log(reg.test("12 3a")) //true
// console.log(reg.test("12 3a")) //true
// console.log("12\n3") //12
//3
// console.log(reg.test("12\n3")) //true
// console.log(reg.test("1")) //false
// console.log(reg.test("a ba")) //true(tab键)
// 4. \S 1位 非空白
// var reg = /\S/
// console.log(reg.test("12 3a")) //true
// console.log(reg.test(" ")) //false
// console.log(reg.test("\n\n\n")) //false
// console.log(reg.test(" ")) //false
//5 \w 字母 数字 下划线
// var reg = /\w/
// console.log(reg.test("&*")) //false
// console.log(reg.test("12abc")) //true
// console.log(reg.test("a")) //true
// console.log(reg.test("1")) //true
// console.log(reg.test("_")) //true
// var reg = /\w\w/
// console.log(reg.test("&*")) //false
// console.log(reg.test("12abc")) //true
// console.log(reg.test("a")) //false
// console.log(reg.test("1")) //false
// console.log(reg.test("_")) //false
//6. \W 非字幕数字下划线
// var reg = /\W/
// console.log(reg.test("&*")) //true
// console.log(reg.test("12abc")) //false
// console.log(reg.test("a")) //false
// console.log(reg.test("1")) //false
// console.log(reg.test("_")) //false
// var reg = /\W\W/
// console.log(reg.test("&")) //false
//7 . 任意内容 (换行不算)
// var reg = /./
// console.log(reg.test("%^*#$")) //true
// console.log(reg.test("123")) //true
// console.log(reg.test("ba\ncd")) //true 有任意一个非换行符
// console.log(reg.test("\n\n\n\n\n")) //false
//8 . \转义字符
var reg = /\d.\d/ // 中间的点识别成了元字符 7 . 任意内容 (换行不算)
console.log(reg.test("1.2")) //true
console.log(reg.test("1a2")) //true
// console.log(reg.test("1a2"))
var reg = /\d\.\d/ // 1.2 2.3 加\转义字符将.转为了普通字符.
console.log(reg.test("1.2")) //true
console.log(reg.test("1a2")) //false
</script>
21-2 边界符
1.^ 限制开头
2.$ 限制结尾边界
3.^开头结束$
<script>
// ^ 开头
// var reg = /^\d/ //开头必须是数字
// console.log(reg.test("aabb2")) //false
// console.log(reg.test("1aabb")) //true
// $ 结尾边界
// var reg = /\d$/ //结尾必须是数字
// console.log(reg.test("aabb2")) //true
// console.log(reg.test("1aabb")) //false
// ^开头结束$
var reg = /^adc$/
console.log(reg.test("abc")) //true
console.log(reg.test("abcd")) //false
console.log(reg.test("dabc")) //false
var reg = /^a\dc$/
console.log(reg.test("a6c")) //true
</script>
21-3 限定符
1. * 0~多次
2. + 1~多次
3. ? 0~1
4. {n} 指定次数
5. {n,} >=n 大于等于n个
6. {n,m} 在n-m个中间
<script>
// 1. * 0~多次
// var reg= /\d*/
// console.log(reg.test("abc")) //true
// console.log(reg.test("abc1")) //true
// console.log(reg.test("abc12")) //true
//2. + 1~多次
// var reg= /\d+/
// console.log(reg.test("abc")) //false
// console.log(reg.test("abc1")) //true
// console.log(reg.test("abc124vb")) //true
// console.log(reg.exec("abc124vb")) //只能捕获124
// //3. ? 0~1
// var reg=/\d?/
// console.log(reg.test("abc")) //true
// console.log(reg.test("ab1")) //true
//4. {n} 指定次数
// var reg=/\d{3}/
// console.log(reg.test("aaa")) //false
// console.log(reg.test("ab12")) //false
// console.log(reg.test("ab123")) //true
// console.log(reg.exec("ab12345")) //只能捕获123
// var reg=/a{3}/
// console.log(reg.test("aaa")) //true
//5. {n,} >=n //大于等于n个
// var reg=/\d{3,}/ //大于等于3个
// console.log(reg.test("aaa")) //false
// console.log(reg.test("ab12")) //false
// console.log(reg.test("ab123")) //true
// console.log(reg.test("ab12345")) //true
// console.log(reg.exec("ab12345")) //能捕获12345
//6. {n,m}
var reg=/\d{3,5}/ //在3-5个中间
// var reg=/a{3}/
console.log(reg.test("aaa")) //false
console.log(reg.test("ab12")) //false
console.log(reg.test("ab123")) //true
console.log(reg.test("ab123456")) //true
console.log(reg.exec("ab123456")) //只能捕获12345
//
var reg2= /c{2}/
console.log(reg2.test("abc")) //false
console.log(reg2.test("decc")) //true
var reg2= /^abc{2}$/
console.log(reg2.test("abc")) //false
console.log(reg2.test("decc")) //false
console.log(reg2.test("332abcc4343")) //true
console.log(reg2.test("abcc")) //true
var reg2= /^abc{2}$/ //开头ab固定,c是两个
console.log(reg2.test("332abcc4343")) //false
console.log(reg2.test("abcc")) //true
</script>
21-4 特殊符号
1.() 整体
2. | 或 ,左右
3.[] 代表1个
4.[^abc] , [^]表示取反
<script>
// 1.() 整体
// var reg2= /(abc){2}/
// console.log(reg2.test("abc")) //false
// console.log(reg2.test("decc")) //false
// console.log(reg2.test("332abcabc4343")) //true
// console.log(reg2.test("abcabc")) //true
// 2. | 或 ,左右
// var reg = /a|b/
// console.log(reg.test("123")) //false
// console.log(reg.test("1a3")) //true
// console.log(reg.test("12b")) //true
// console.log(reg.test("1ab")) //true
// var reg2 = /(abc|def)/ //只能管前后一个字符
// console.log(reg3.test("abcef")) //true
// console.log(reg3.test("abc")) //true
// console.log(reg3.test("abdef")) //true
// console.log(reg3.test("def")) //true
// var reg2 = /abc|def/ //只能管前后一个字符
// console.log(reg3.test("abc")) //true
// console.log(reg3.test("def")) //true
// var reg3 = /(abc)|def|xyz/
// console.log(reg3.test("abc")) //true
// console.log(reg3.test("def")) //true
// console.log(reg3.test("xyz")) //true
// console.log(reg3.test("xy")) /false
//3 [] 代表1个
var reg = /[abcdef]/ //包含其中一个即可
console.log(reg.text("x")) //false
console.log(reg.text("xa")) //ture
var reg = /[abcdef]{3,5}/ //至少包含3-5个
console.log(reg.text("abcd")) //ture
console.log(reg.text("abxyz")) //false
var reg = /[a-w]{3,5}/
// console.log(reg.test("xabc"))
console.log(reg.test("abcd")) //false
console.log(reg.test("abxyz")) //ture
console.log(reg.test("111abxy222")) //ture
// [a-zA-Z0-9_] \w
// [0-9] \d
//4 [^abc]
var reg2 = /[^abc]/ //[^]表示取反
console.log(reg2.test("a")) //false
console.log(reg2.test("xyz")) //true 一个不在就对
console.log(reg2.test("abz")) //true
</script>
21-5 捕获exec
1. exec() 捕获片段
2. 标识符 g全局标识符 i忽略大小写
<script>
// test()
// exec() 捕获片段
// var reg = /\d{3}/
// console.log(reg.exec("aa123aa")) //null
// console.log(reg.exec("aa123aa")) //123
var datestr = "time is from 2029-01-01 12:20:20 to 2029-11-01 12:20:20"
// 2029/01/01 - 2029/11/01
// var reg = /\d{4}-\d{1,2}-\d{1,2}/
// var newdatestr = reg.exec(datestr)
// console.log(newdatestr)
// console.log(newdatestr[0].split("-").join("/"))
//只能截取遇到的第一个 2029/01/01
// var newdatestr = reg.exec(datestr)
// console.log(newdatestr)
// var newdatestr = reg.exec(datestr)
// console.log(newdatestr)
// console.log(newdatestr[0].split("-").join("/"))
//同样只能截取遇到的第一个 2029/01/01
// 标识符 g i
//g全局标识符
var reg = /\d{4}-\d{1,2}-\d{1,2}/g //全局标识符
var newdatestr1 = reg.exec(datestr)
console.log(newdatestr1)
var newdatestr2 = reg.exec(datestr)
console.log(newdatestr2)
var newdatestr3 = reg.exec(datestr)
console.log(newdatestr3)
console.log(newdatestr1[0].split("-").join("/"))
console.log(newdatestr2[0].split("-").join("/"))
//2029/01/01
//2029/11/01
var reg = /(\d{4})-(\d{1,2})-(\d{1,2})/g //全局标识符
var newdatestr1 = reg.exec(datestr)
console.log(newdatestr1)
var newdatestr2 = reg.exec(datestr)
console.log(newdatestr2)
var newdatestr3 = reg.exec(datestr)
console.log(newdatestr3)
console.log(newdatestr1[0].split("-").join("/"))
console.log(newdatestr2[0].split("-").join("/"))
//2029/01/01
//2029/11/01
//加()后()内内容也会被单独捕获,但不显示在最终结果上
//i忽略大小写
var myreg= /[a-z]/
console.log(myreg.test("AA")) //false
console.log(myreg.exec("AA")) //null
var myreg= /[a-z]/i //忽略大小写
console.log(myreg.test("AA")) //true
console.log(myreg.exec("AA")) //A
// /\d/ig 既忽略大小写,也是全局的查找
</script>
21-6 正则表达式的两大特性
1. 懒惰 每次从字符串开始的地方找 解决:使用全局标识符g
2. 贪婪 把符合规则的最大可能性匹配出来
3. 非贪婪?
<script>
//1.懒惰, 解决 使用全局标识符g
//2.贪婪
// var reg = /\d{1,4}/
// console.log(reg.text("aa123456bb")) //true
// console.log(reg.exec("aa123456bb")) //1234 能拿多少拿多少
//3.非贪婪?
var reg = /\d{1,4}?/
console.log(reg.exec("aa123456bb")) //1 尽可能少的拿
/*
*? 非贪婪 //*贪婪
+? 非贪婪
?? 非贪婪
{n,}? 非贪婪
{n,m}? 非贪婪,按最小的n满足
*/
var str = `<p class="active"><span>kerwin</span></p>`
var myreg = /<p.*>/ //贪婪
console.log(myreg.exec(str)) //`<p class="active"><span>kerwin</span></p>`
var myreg = /<p.*?>/ //非贪婪
console.log(myreg.exec(str)) //<p class="active">
</script>
21-7 正则与字符串方法
1.replace替换
2.search查找
3.match捕获内容
<script>
// 正则.test(字符串)
// 正则.exec(字符串)
//字符串.replace替换 search查找 match捕获内容
//replace
// var newstr = str.replace("a","*") //只能替换第一个
// var newstr = str.replace(/a/g,"*") //可以替换全局
// console.log(newstr)
//search
// console.log(str.search("a"))
// console.log(str.search(/a/))
// console.log(str.search(/ax/))
//match 捕获内容
var datestr = "time is from 2029-01-01 12:20:20 to 2029-11-01 12:20:20"
// console.log(str.match("ad"))
console.log(datestr.match(/(\d{4})-(\d{1,2})-(\d{1,2})/g))
</script>
案例:密码强度验证
<!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>
* {
margin: 0;
padding: 0;
}
form {
width: 500px;
padding: 20px;
border: 3px solid #333;
margin: 50px auto;
}
form > label {
width: 100%;
height: 70px;
}
form > label > input {
width: 100%;
box-sizing: border-box;
padding-left: 30px;
font-size: 20px;
height: 50px;
}
form > p {
width: 100%;
margin-top: 10px;
display: flex;
justify-content: space-between;
}
form > p > span {
width: 30%;
background-color: #ccc;
color: #fff;
height: 30px;
font-size: 20px;
line-height: 30px;
text-align: center;
}
form > p > span:nth-child(1).active {
background-color: red;
}
form > p > span:nth-child(2).active {
background-color: orange;
}
form > p > span:nth-child(3).active {
background-color: green;
}
</style>
</head>
<body>
<form>
<label>
<input type="text">
</label>
<p>
<span >弱</span>
<span >中</span>
<span >强</span>
</p>
</form>
<script>
var oinput =document.querySelector("input")
var reg1 = /\d/
var reg2 = /[a-z]/i
var reg3 = /[!@#$%^&*()]/
var ospan = document.querySelectorAll("span")
oinput.oninput = function(evt){
console.log(this.value)
// console.log(evt.target.value)
var level = 0
if(reg1.test(this.value)) level++
if(reg2.test(this.value)) level++
if(reg3.test(this.value)) level++
// console.log(level)
for(var i=0;i<ospan.length;i++){
ospan[i].classList.remove("active")
if(i<level){
ospan[i].classList.add("active")
}
}
}
</script>
</body>
</html>
22. this 关键字
22-1 this指向
-
每一个函数内部都有一个关键字是
this可以让我们直接使用的 -
重点: 函数内部的 this 只和函数的调用方式有关系,和函数的定义方式没有关系
-
函数内部的 this 指向谁,取决于函数的调用方式
全局定义的函数直接调用,this => window
```javascript
function fn() {
console.log(this)
}
fn()
// 此时 this 指向 window
```
对象内部的方法调用,this => 调用者
```javascript
var obj = {
fn: function () {
console.log(this)
}
}
obj.fn()
// 此时 this 指向 obj
```
定时器的处理函数,this => window
```javascript
setTimeout(function () {
console.log(this)
}, 0)
// 此时定时器处理函数里面的 this 指向 window
```
事件处理函数,this => 事件源
```javascript
div.onclick = function () {
console.log(this)
}
// 当你点击 div 的时候,this 指向 div
```
自调用函数,this => window
```javascript
(function () {
console.log(this)
})()
// 此时 this 指向 window
```
22-2 改变this指向
call 和 apply 和 bind
- 刚才我们说过的都是函数的基本调用方式里面的 this 指向
- 我们还有三个可以忽略函数本身的 this 指向转而指向别的地方
- 这三个方法就是 call / apply / bind
- 是强行改变 this 指向的方法
1.call
-
call方法是附加在函数调用后面使用,可以忽略函数本身的 this 指向 -
语法:
函数名.call(要改变的 this 指向,要给函数传递的参数1,要给函数传递的参数2, ...)var obj = { name: 'Jack' } function fn(a, b) { console.log(this) console.log(a) console.log(b) } fn(1, 2) fn.call(obj, 1, 2)fn()的时候,函数内部的 this 指向 windowfn.call(obj, 1, 2)的时候,函数内部的 this 就指向了 obj 这个对象- 使用 call 方法的时候
- 会立即执行函数
- 第一个参数是你要改变的函数内部的 this 指向
- 第二个参数开始,依次是向函数传递参数
2.apply
-
apply方法是附加在函数调用后面使用,可以忽略函数本身的 this 指向 -
语法:
函数名.apply(要改变的 this 指向,[要给函数传递的参数1, 要给函数传递的参数2, ...])var obj = { name: 'Jack' } function fn(a, b) { console.log(this) console.log(a) console.log(b) } fn(1, 2) fn.call(obj, [1, 2])fn()的时候,函数内部的 this 指向 windowfn.apply(obj, [1, 2])的时候,函数内部的 this 就指向了 obj 这个对象- 使用 apply 方法的时候
- 会立即执行函数
- 第一个参数是你要改变的函数内部的 this 指向
- 第二个参数是一个 数组,数组里面的每一项依次是向函数传递的参数
3.bind
-
bind方法是附加在函数调用后面使用,可以忽略函数本身的 this 指向 -
和 call / apply 有一些不一样,就是不会立即执行函数,而是返回一个已经改变了 this 指向的函数
-
语法:
var newFn = 函数名.bind(要改变的 this 指向); newFn(传递参数)var obj = { name: 'Jack' } function fn(a, b) { console.log(this) console.log(a) console.log(b) } fn(1, 2) var newFn = fn.bind(obj) newFn(1, 2)- bind 调用的时候,不会执行 fn 这个函数,而是返回一个新的函数
- 这个新的函数就是一个改变了 this 指向以后的 fn 函数
fn(1, 2)的时候 this 指向 windownewFn(1, 2)的时候执行的是一个和 fn 一摸一样的函数,只不过里面的 this 指向改成了 obj
<button id="btn">click</button>
<script>
// call apply bind
var name = "1111111111111111111111"
var obj1 = {
name:"obj1",
getName:function(a,b,c){
console.log("getName1",this.name)
console.log("参数",a,b,c)
}
}
var obj2 = {
name:"obj2",
getName:function(){
console.log("getName2",this.name)
}
}
// console.log(obj1)
// obj1.getName()
// obj2.getName()
// call 执行函数, 并改变this执行为函数的第一个参数
// 支持多个参数
obj1.getName.call(obj2,1,2,3) //参数 1 2 3
// apply 执行函数, 并改变this执行为函数的第一个参数
// 只支持两个参数, 第二个参数是一个数组
obj1.getName.apply(obj2,[1,2,3]) //参数 1 2 3
// obj1.getName.call(window)
//bind 改变this指向为函数的第一个参数,不会自动执行函数
// 支持多个参数
var fun1 = obj1.getName.bind(obj2,1,2,3)
console.log(fun1)
fun1() //手动执行
btn.onclick = handler.bind(window)
function handler(){
console.log(11111,this)
}
</script>