正则表达式
什么是正则表达式:定义字符串中字符出现规则的表达式
何时使用:分割、替换、验证
语法:
/正则表达式/;
1、最简的正则:/关键字原文/"no" -> /no/后缀
后缀:g:全部 i:忽略大小写
2、备选字符集:/[备选字符集]/;
强调:1、一个中括号,只管一位字符
2、正则表达式默认只要满足了就不管后续了,我们希望从头到尾完全匹配,解决:前加^后加$:/^[备选字符集]$/;
特殊:如果备选字符集中ascii码是连续的,那么中间部分可以-省略
比如:以为数字:[0-9]
一位字母:[A-Za-z];
一位数字、字母、下划线:[0-9A-Za-z_]
一位汉字:[\u4e00-u9fa5]
除了xxx之外的:[^0-9] - 很少使用,范围太广了
3、预定义字符集:前辈们提前预定义了一些字符集,方便我们程序员 - 简化备选字符集
一位数字:\d => [0-9]
一位数字、字母、下划线:\w = >[0-9A-Za-z_];
一位空白字符:空格、回车、制表符\s
一位除了换行之外的任意字符:. - 很少使用,范围太广了
建议:优先使用预定义字符集,预定义字符集满足不了再用备选字符集补充
4、问题:不管是预定义字符集还是备选字符集,一个都只管一位
量词:规定一个字符集出现的次数:
1、有明确数量:
字符集{n,m}:前边相邻的字符集,最少n次,最多m次
字符集{n,}:前边相邻的字符集,最少n次,多了不限
字符集{n}:前边相邻的字符集,必须n次
2、无明确数量:
字符集?:前边相邻的字符集,可有可无,最多一次
字符集*:前边相邻的字符集,可有可无,多了不限
字符集+:前边相邻的字符集至少一次,多了不限
5、选择和分组:
选择:在两个规则中选择一个
规则1|规则2
分组:将多个字符集临时组成一组规则
(规则1|规则2)
6、指定匹配位置:
开头:^
结尾:$
特殊:两者同时出现,前加^后加$,表示从头到尾要求完全匹配 - 只要是做验证必须加上
7、预判:密码强度验证
/^(?![0-9]+$)[0-9A-Za-z]{4}$/; - 前面的预判意思是:不能纯由数字组成,可能由大写、小写
/^(?![A-Za-z]+$)[0-9A-Za-z]{4}$/; - 前面的预判意思是:不能纯由大写字母组成,也不能纯由小写字母组成,也不能纯由大写和小写字母组成
/^(?![0-9a-z]+$)(?![A-Za-z]+$)[0-9A-Za-z]{4}$/; - //4位密码,数字和字母都可以,至少要有一位大写和一位数字。
/^(?![0-9a-z]+$)(?![A-Za-z]+$)(?![A-Z0-9]+$)[0-9A-Za-z]{4}$/; - //4位密码,数字和字母都可以,至少要有一位大写和一位数字和一位小写。
/^(?![0-9A-Za-z]+$)[0-9A-Za-z\u4e00-\u9fa5]{4}$/ - //至少要有一位汉字
String支持正则的API:
1、分割:var arr=str.relace(str/reg,"新内容");
//replace支持正则,搭配上后缀就可以替换所有的关键字,而且替换往往都要加后缀
//问题:只能替换为固定的内容
2、高级替换法:
var newStr=str,replace(/[][][][][]+/g,function(a,b,c){
console.log(a);//要替换的关键字 - 正则匹配到的关键字
console.log(b);//要替换的关键字的下标 - 正则匹配到的关键字的下标
console.log(c);//原文本身
return a.length==2?"**":a.length==3?"***":"***";
});
3、格式化:
var idCard="500243199805207472";
var reg=/\d{4}(\d{4})(\d{2})(\d{2})\d{4}/;
idCard=idCard.replace(reg,function(a,b,c,d){
//在replace的时候,如果正则出现了分组,那么我们会得到更多的形参
//再形参a的后就会再出现n个形参,具体多少个看有多少个分组
//第一个分组获取到的内容会保存在第二个形参之中
//第二个分组获取到的内容会保存在第三个形参之中
//...
//倒数两个形参分别是下标和原文
return b+"年"+c+"月"+d+"r+”日";
})
正则对象: 创建:
1、直接量方式:var reg=/正则表达式/后缀;
2、构造函数方式:var reg=new RegExp("正则表达式","后缀");
方法:1个
验证:var bool=reg.test(用户输入的);
true->说明用户输入正确
flase->说明用户输入错误
Math数学对象:专门提供了数学计算的API
强调:不需要创建,直接使用的,有浏览器的js的解释器自动创建
属性:Math
方法:
1、取整:
1、上取整:超过一点点,就会取下一个整数
var num=Math.ceil(num);
2、下取整:无论超过多少,都会省略小数部分
var num=Math.floor(num);
3、四舍五入取整:
var num=Math.round(num);//进制只看小数的第一位
//取整方式:以上三个+parseint(str)+*num.toFixed(d);
个人推荐:*num.toFixed(d),优点:可以四舍五入保留指定小数位数
缺点:返回的结果是一个字符串,建议搭配上parseFloat一起使用
笔试题:不允许使用toFixed的情况下,自己封装一个函数,实现toFixed的功能,并且最后返回一个数字,看用户提供的数字和保留几位小数,对着用户的这个数字*10的几次方(保留几位小数),在使用Math.round四舍五入取整对着这个数字/10的几次方(保留几位小数)
2、乘方:Math.pow(底数,幂) === 底数**幂
开平方:Math.sqrt(num)
3、绝对值:把负数转为正数
Math.abs(num);
4、最大值和最小值:
var max/min=Math.max/min(a,b,c,d,e.....);
问题:本身不支持数组参数的
解决:固定用法:
var max/min=Math/min.apply(Math,arr);
apply其中一个功能是可以将数组打散为单个元素
5、随机整数:Math.random() - 在0-100之间取出一个随机的小数,可能取到0,但是绝对不可能取到1,意味着可能取到最小数,但是不能取到最大数
公式:parseint(Math.random()*(max-min+1)+min);
Date日期对象
创建:
1、创建一个当前日期时间:
var now=new Date();
2、创建一个自定义时间:
var birth=new Date("yyyy/MM/dd hh:mm:ss");
3、创建一个自定义时间:
var birth=new Date(yyyy,MM,dd,hh,mm,ss);
//修正月份:从0开始的,0 => 11月
4、复制一个日期:
为什么:日期的所有的API都是直接修改原日期的,无法获得修改之前的日期,所以,在执行API之前先进行复制,然后在对复制的日期进行操作
var end=new Date(start);
操作:
1、两个日期对象之间可以相减,得到一个毫秒差,通过毫秒差就可以换算出你想要的任何一部分 - 日期的本质其实就是保存的毫秒差
var date=new Date(毫毛数);
2、API:
分量:时间的单位
年月日星期:FullYeay、Month、Date、Day
时分秒毫秒:Hours、Minutes、Seconds、Milliseconds
每一个分类都有一对儿getXXX/setXXX
其中getXXX负责获取某一个分量的值
其中setXXX负责设置某一个分量的值
特殊:
1、取值范围:
FullYeay - 当前的年份
MOnth - 0~11
Date - 1~31
Day:0~6
Hours:0~23
Minbtes、Seconds:0~59
2、在设置时间的时候,如果超过了范围,会自动进制
3、Day是不允许设置的
3、如果希望对某个分量进行加减操作,推荐一句话完成
date.setXXX(date.getXXX()+/-num)
4、格式化日期为字符串:
作用:1、date->string:stringAPI更多更实用
2、默认的标准国际日期,不是所有人都认识
date.toLocaleString();//转本地字符串
问题:存在兼容问题
解决:自定义日期格式化format
Error错误对象:
1、快速找错
2、记得有时候可能要防一手用户
1、浏览器自带四种错误类型,可以快速找到自己的错误:
语法错误:SyntaxError-多半是语法、符号错了
引用错误:ReferenceError-没有创建过却使用了
类型错误:TypeError-不是你的方法/属性却用了
范围错误:RangeError-只是一个API:num.toFixed(d);//d取值范围的,0~100之间
2、只要发生错误,就会报错,会导致后续代码终止执行了(后面代码没有效果、如果做的是APP、软件发生报错,则会闪退体验感差)我们不希望
错误处理:就算发现错误,我们也不希望报错而是给一个错误提示,后续代码依然可以继续执行
语法:
try{
只放可能出错的代码
}catch(err){
只有发生错误后才会执行
}
try...catch...的性能很差,几乎是所有代码中效率最差的
可用一个技术代替:if...else...
开发经验:提前预判用户:记住一切的客户端输入/用户输入都是坏人-一定要做好防护
3、抛出自定义错误:
throw new Error("自定义错误描述")
function:
1、创建:
声明方式:function 函数名(形参列表){函数体 return返回值}-具有完整的声明提前
直接量方式:var 函数名=function(形参列表){函数体 return返回值}-只提前函数名部分,函数名其实就是一个变量
构造函数:var 函数名=new function(“形参1”,形参(2),...,"函数体");
何时:如果你的函数体不是固定的,而是动态拼接的(函数体现在毕竟是一个字符串)
2、调用:
var 接住结果=函数名(实参列表)
3、考点:
1、如何创建
2、什么是作用域
3、什么是声明提前
4、什么是按值传递
5、什么是重载:相同的函数名,传入不同的实参,可以自动选择对应的函数执行
为什么:减轻程序员的压力
问题:js的语法不支持重载的
js不允许多个同函数名存在,如果同时存在,最后的会覆盖之前的
解决:在函数中有一个对象-arguments对象
什么是arguments:自动创建的,是一个类数组对象,不是数组
作用:接收所有的实参
以后有没有实参无所谓了,变相的实现了重载,可以在函数内部判断arguments的不同,执行不同的操作
只有3个点和数组相同:
1、都有下标
2、都有length
3、都可以遍历
正式开发中,开发结束后,需要做代码优化,可能就会将多个函数整合为一个函数
匿名函数:没有名字的函数,理论上来说我们无法调用
1、自调:函数自己调用自己
语法:
(function(){
//代替全局代码
})();
特点:自调的代码只能执行一次===全局代码
为什么:节约内存,因为匿名函数,没有变量引用着,用完后,就会立即释放
2、回调:将函数作为了实参,传递给其它函数使用
1、学习回调的目的:让我们知道哪些讲回调,匿名函数,只要不是自调,就是回调
arr.sort(function(a,b){return a-b})
str.replace(reg,function(){})
btn.onclick=function(){}
2、ES6有一个技术箭头函数:简化一切的回调函数
function:
作用域:
1、全局:随时可以用,可以反复使用。缺点:容易污染
2、局部:只能在函数调用时内部可用,不会被污染。缺陷:一次性的,是会自动释放的
函数执行的原理:
1、程序加载时:
创建执行环境栈(ECS):保存了函数调用的顺序的数组
首先压入全局执行环境(全局EC)
全局EC引用着全局对象window
window中保存着全局变量
2、定义函数时:
创建函数对象:封装代码段
在函数对象中有一个scope(作用域)属性:记录着函数来自的作用域是哪里
全局函数的scope都是window
3、调用前:
在执行环境栈(ECS)压入一个新的EC(函数的EC)
创建活动对象(AO):保存着本次函数调用时用到的局部变量
在函数中的EC有一个属性scope chain(作用域链)引用AO
4、调用时:
正是因为有了前三个步骤,我们才有了变量的使用规则:优先使用局部的,局部没有找全局,全局没有就报错
5、调用完:
函数的EC会出栈,AO无人引用,垃圾回收器登场,AO自动释放,局部变量也就自动释放
两链一包:
作用域链:以函数的EC为起点,经过AO,逐级引用,形成的一条链式结构我们就称之为作用域链
何时使用:保护一个可以反复使用的局部变量
如何使用:
1、两个函数进行嵌套
2、外层函数创建收到保护的变量
3、外层函数return出内层函数
4、内层函数要去操作受保护的变量
强调:
1、判断是不是闭包,有没有两层函数嵌套,返回内层函数,内层函数在操作外层受保护的变量
2、外层函数调用几次,就创建了几个闭包,受保护的变量就有了几个副本
3、同一次外层函数调用,返回的内层函数,都是在操作同一个受保护的变量
缺陷:受保护的变量,永远不会被释放,使用过多,会导致内存泄漏
问题:应该在哪里使用?使用场景:防抖节流
三个事件需要防抖节流:
1、elem.onmousemove-频繁的修改DOM树,映像性能
2、input.oninput-每次input的内容修改都会触发,性能不好
3、window.onresize
xxx.以上三个事件=function(){
inner();
}
公式:
function fdjl(){
var timer=null;//局部的timer准备保存定时器,定时器的序号
return function(){
if(timer!==null){clearTimeout(timer)}//停止一次性定时器
timer=setTimeout(function(){
操作
},1000)
}
}
var inner=fdjl();
Object对象:
1、面向对象:三大特点:封装、继承、多态
1、笔试题:简单的说一说面向对象和面向过程开发方式的区别
面向对象:对象,js有一句话万物皆对象,假设一个人是一个对象的话
面向过程:经过:开始-结束,我们一直的开发方式都是面向过程:先干什么在干什么最后干什么
为什么要面向对象:现实生活中所有的数据都必须包含在一个事物中才有意义
何时要使用面向对象开发方式:以后做任何操作都要封装在一个对象中
2、封装:创建自定义对象:
1、直接量:
var obj={
"属性名":属性值,
...
"方法名":function(){操作},
...
};
特殊:
1、其实属性名和方法名的“”可以不加的
2、访问对象的属性和方法
obj.属性名
obj.方法名()
js有一句话万物皆对象,一切对象的底层都是hash数组
3、访问到不存在的属性,返回undefined
4、可以随时随地的添加新属性和方法
5、箭头函数this->window
6、构造函数中的this->当前正在创建的对象
2、预定义构造函数方式:var obj=new Object();//空对象
//需要后续自己慢慢添加
obj.属性值;
obj.方法名=function(){}
以上两个方法都有一个缺陷:一次只能创建一个对象
3、批量创建对象:自定义构造函数方式
1、创建自定义构造函数
function 类名(name,age,hobby){
this.nanme=name;
this.agage;
this.hobby=hobby;
}
2、调用构造函数创建出对象
var obj=new 类名(实参列表);
面向对象:
优点:
1、逼格高,所有的属性和方法都保存在一个对象之中
2、每个功能特地放开些-便于后期维护,哪怕没有注释,我也能一眼看懂代码
铁索链舟-一个方法触发多个方法联动
缺点:对新手不友好,this指向变来变去的