正则
正则表达式
1.最简单的正则表达式
关键字原文本身/原文/ig
i:忽略大小写
g:global全局
2.备选字符集
【一个备选字符集】规定了【一位字符】可用的备选字符列表/[备选字符集]/
注意:
-
一个[]只能匹配一位字符
-
正则默认只要满足后,就不再管理后续操作,用户可任意输入
- 解决:/^[备选字符集]$/ 要求从头到尾完全匹配
-
若备选字符集中,unicode号连续,中间部分可用-代替
//例
[0123456789] => [0-9]
一位字母 [a-zA-Z]
一位汉字 [\u4e00-\u9fa5]
一位数字、字母、下划线 [0-9a-zA-Z_]
-
除了x以外,其他都可以
[^x]
3.预定义字符集
已提供的常用字符集的简化
-
一位数字 [0-9]
\d -
一位数字、字母、下划线 [0-9a-zA-Z_]
\w -
一位空白字符(\t \n 空格)
\s -
一位除换行外的任意字符
.
不管是备选字符集还是预定义字符集,一个字符集都只能控制一个字
4.量词
规定了一个字符集出现的次数
-
有明确数量
-
字符集{n,m} 最少n次,最多m次
-
字符集{n,} 最少n次,多列不限制
-
字符集{n} 只能n次
-
-
无明确数量
-
字符集? 前面相邻的字符集可有可无,但最多一次
-
字符集* 前面相邻的字符集可有可无,且不限制数量
-
字符集+ 前面相邻的字符集至少一次,且不限制数量
-
5.指定匹配的位置
^开头 &结尾
注意:若^和&同时出现,前加^、后加&,要求从头到尾完全匹配
6.选择和分组
-
选择|:在多个规则中,选择满足的规则执行
规则1|规则2 -
分组()
(规则1|规则2)
//例
/^\d|\w$/ //开头数字,结尾空格
/^(\d|\w)$/ //从头到尾,只能是空格或者数字
//电话的正则
/^(\+86|0086)?\s*1[3-9]\d{9}$/
7.预判
用于密码强度
//例
(?![0-9]+$) //不能全由数字组成
(?![0-9A-Z]+$) //不能全由数字或大写字母组成,也不能只由数字或大写字母组成
字符串中支持正则的API
1.分割
var arr=str.split(reg)
2.替换
- 基本替换法
var newStr=str.replace(reg,"新内容")
默认只会替换第一个关键字,若想全部替换,结尾添加g
替换的内容只能是一个固定的新内容
- 高级替换法
var newStr=str.replace(正则,function(a,b,c){
console.log(a);//正则匹配到的关键字
console.log(b);//正则匹配到的关键字下标
console.log(c);//原文本身
return a.length==2?"**":"***";
})
- 格式化
//根据身份证号匹配出生日
var str="123123123412234567";
var newStr=str.replace(/(\d{6})(\d{4})(\d{2})(\d{2})(\d{4})/,function(a,b,c,d,e,f,g,h){
console.log(a);//正则匹配到的关键字
console.log(b);//是第1个分组获取到的内容
console.log(c);//是第2个分组获取到的内容
console.log(d);//是第3个分组获取到的内容
console.log(e);//正则匹配到的关键字的下标
console.log(f);//原文本身
return c+"年"+d+"月"+e+"日";
})
console.log(newStr);
正则对象
1.创建正则对象
-
直接量方法
var reg=/正则表达式/后缀 -
构造函数:拼接正则情况使用
var reg=new RegExp("正则表达式","后缀")
2.方法
var bool=reg.test(user);结果:true/false
Math
专门提供了数学计算的API,不需要创建,直接使用
唯一的属性
Math.PI
API
1.取整
-
上取整(超过一点就会取下一整数)
Math.ceil(num) -
下取整(超多多少都会省略小数部分)
Math.floor(num)- 上取整和下取整针对的对象小数位数都不能超过15位,超过会失效
-
四舍五入取整
Math.round(num)四舍五入:
num.toFixed(d);即可四舍五入,又可自定义小数位数。结果为字符串parseFloat(num.toFixed(d));
//封装一个函数,实现可自定义保留小数位数且四舍五入
function round(num,d){
num*=Math.pow(10,d);
num=Math.round(num);
num/=Math.pow(10,d);
return num;
}
console.log(round(Math.PI,3));
2.乘方和开方
-
乘方
Math.pow(底数,幂) -
开方
Math.sqrt(num)只能开平方
3.最大值/最小值
Math.max/min(a,b,c,d,...)
问题:不支持数组参数 ==> 解决:Math.max/min.apply(Math,arr);
apply:①自己没有的方法,可以去借用;②可将数组打散为单个参数进行传入
4.绝对值
Math.abs(num) 将负数转为正数
5.随机数
Math.random(); 0-1的随机数(可能取到0,但无法取到1)
只要页面具有随机功能,底层均为随机数
重要使用方法
Math.random()*(max-min+1)+min;
parseInt(Math.random()*(max-min+1)+min);
Date
封装了日期对象,提供了对日期事件进行操作的API
创建日期对象
-
当前时间
var now=new Date(); -
自定义时间1
var birth=new Date("yyyy/mm/dd h:m:s");-
自己创建,放入“年/月/日 时:分:秒”
-
时分秒可以省略,未写时默认00:00:00
-
-
自定义时间2
var birth=new Date(yyyy,mm,dd,h,m,s);- 月份需要修正,默认从0开始到11
-
复制一个日期对象
var end=new Date(now);- 因为日期对象的API都是直接修改原对象,使用API后无法保存旧值,调用API后无法保存旧值 => 调用API前先复制保存
-
var x=new Date(毫秒数);
计算器保存的时间初始值:1970年1月1日 8:00:00
操作
1.减法
两个日期对象相减,得到的是毫秒差 ==> 日期对象保存的是毫秒
2.API
分量:FullYear Month Date Day Hours Minutes Seconds
-
每一个分量都有一对方法
getxx/setxx ()-
取值范围:年(当前年份)、月(0-11)、日、时(0-23)、分(0-59)、秒(0-59)
-
星期Day:只有get,没有set,取值0-6(0是星期天)
-
-
对某个日期直接做加减
date.setFullYear(date.getFullYear()+3); -
将日期格式化为字符串
date.toLocaleString();
+ 优点:转为String,可以使用String的API
+ 缺点:具有浏览器兼容性
解决:自定义format函数
Number Boolean
所有引用类型底层都具有构造函数创建方式(除Math),直接量法是后续追加的简化操作
var num=new Number();
var bool=new Boolean();
num.toString();
num.toFixed(d);//结果是一个字符串
Error
1.浏览器自带的4种错误类型
-
语法错误:SyntaxError --常为符号错误
-
引用错误:ReferenceError --未创建就使用了
-
类型错误:TypeError --有这个方法,但不是这个类型的方法
-
范围错误:RangeError --只有num.toFixed(d)会有这个错误,d的范围:0-100
2.错误处理
当程序发生错误时,保证程序不会异常中断的机制
try{
可能出错的代码
}catch(err){
console.log(err);//提示用户错误的原因
}
但try...catch语句执行效率低 ==> if...else
3.抛出自定义错误
throw new Error("自定义错误信息")
Function
创建
-
声明方式:
function 函数名(形参){函数体; return 结果;}具有完整的声明提前 -
直接量方式
var 函数名=function(形参){函数体; return 结果;}有声明提前,但赋值留在原地 -
构建函数法:
var 函数名=new Function("形参",...,"函数体")函数体在动态拼接时使用
调用
-
函数名();
-
元素.onclick
重点
1.创建:3种方式
2.作用域
-
全局:哪里都可以使用
-
函数:只能在函数调用时内部使用
-
变量的使用规则:优先使用局部,局部没有找全局,全局没有则报错
3.声明提前
在程序正式执行前,会将var声明的变量和function声明的函数集中提前到当前作用域顶部,但赋值留在原地
4.按值传递
-
原始类型之间 互不影响
-
引用类型之间 相互影响
5.重载
相同的函数根据传入的实参不同,会自动选择相应函数执行
目的:减少程序员负担
注意:js不支持重载,因为js不允许同时存在多个同名函数,最后一个会覆盖之前的所有函数
arguments 函数内部使用,类数组:下标、length、遍历
作用:可以借助实参,则不需要创建形参
使用arguments实现重载:通过判断arguments,实现功能
//传入一个实参做乘方,传入两个实参做加法
function f1(){
if(arguments.length==1){
return Math.pow(arguments[0],2);
}else if(arguments.length==2){
return arguments[0]+arguments[1];
}
}
console.log(f1(8));
console.log(f1(8,9);
6.匿名函数
无名字的函数,被没有变量名/函数名引用着,调用完毕后会立即释放
-
匿名函数自调
(function(){函数体;})() -
匿名函数回调:某个函数调用时,传入的实参是一个函数,且不需要调用执行
//例
arr.sort(function(a,b){return a-b;})
str.replace(reg,function(){})
认识回调函数: 匿名函数不是自调就是回调
7.闭包
函数的执行原理
① 程序在加载时:创建执行环境栈(ECS),首先压入全局执行环境(全局EC),全局EC中引用着全局对象window,window中保存着全局变量
② 定义函数时:创建函数对象,封装函数的定义。在函数对象中创建scope属性(记录自己来自的作用域)。全局函数的scope是window
③ 调用函数前:在执行环境栈中压入新的函数EC。创建活动对象AO,保存着本次函数调用时用到的局部变量。在EC中添加scope chain属性引用AO,设置AO的parent属性为函数的scope对象
④ 调用时:变量的使用规则是有限使用局部,局部没有找全局,全局没有报错
⑤ 调用完:函数的EC会出栈,AO会自动释放,故局部变量自动释放
作用域链scope chain
-
概念:以EC中的scope chain属性为起点,经过AO逐级引用,形成的一条链式结构,称为作用域链
-
作用:查找变量
闭包
-
概念:保护一个可以【反复使用的局部变量】的一种词法结构,结合了局部和全局的优点
-
使用步骤:
-
创建一个外层函数
-
在其中创建一个受保护的局部变量
-
外层函数调用要返回内层函数,此内层函数在操作受保护的变量
-
-
缺点:受保护的变量永远无法释放,用多了会导致内存泄漏
-
闭包的重点:
-
判断闭包,找到受保护的变量,确定其值
-
外层函数调用几次,就创建了几个闭包,受保护的变量就有了几个副本
-
同一外层函数调用,返回的内层函数,都是在使用同一个受保护的变量
-
//语法
function 外层函数(){
受保护的变量;
return function(){
不断操作受保护的变量;
return 结果;
}
}
var 内层函数=外层函数();
- 开发:防抖节流
-
elem.onmousemove 鼠标移动事件,每次移动都会触发
-
input.oninput input每次修改都会触发的事件
-
window.onresize 屏幕每次改变大小都会触发
-
//防抖节流
function fdjl(){
var timer=null;
return function(){
if(timer){clearTimeout(timer)}//判断有无定时器,有则清除
timer=setTimeout(function(){
操作;
},毫秒数)
}
}
var animate=fdjl();
Object
面向对象: 在程序中使用对象描述现实中的一个事物
-
现实事物的属性 => 对象的属性
-
现实事物的方法 => 对象的函数
-
现实中的所有数据都必须包含在事物中才有具体意义
面向对象和面向过程
-
面向过程:开头->中间->结束,一直使用的开发方法
-
面向对象:对象则包含属性和方法,如轮播对象、选项卡对象
10个引用类型都是对象(浏览器内置对象)
封装/创建/定义/声明/实例化:自定义创建对象
1.直接量法
var obj={"属性名":"属性值","方法名":function(){},}
注意:
-
属性名和方法名的""可以省略,但通常不省略,因为JSON必须添加""
-
访问对象属性和方法
-
obj.属性名;=== obj["属性名"]; -
obj.方法名()=== obj["方法名"]();
-
-
访问到不存在的属性:undefined(下标越界)
-
可在后续随时添加想要的东西
obj.新属性名="属性值";
this 在当前对象的方法内,指向的当前调用方法对象
① 单个元素绑定事件 this -> 单个元素
② 多个元素绑定事件 this -> 当前元素
③ 函数 this -> 当前调用函数的对象
④ 构造函数中 this -> 当前创建的对象
⑤ 定时器 this -> timer
2.预定义构造函数法
var obj=new Object();//创建一个空对象
obj.属性名=属性值;
obj.方法名=function(){};
3.自定义构造函数法
-
创建一个构造函数
function 类名(形参,...){this.属性名=形参1;...} -
反复调用构造函数,创建出多个对象
var x=new 类名(实参,...); -
遍历
for(var i in obj){obj[i]} -
优点
-
所有操作都包含在一个对象中
-
维护效率高
-
一个方法调用,触发了很多操作
-
继承
父元素的成员(属性和方法),子对象可以直接使用
为什么继承:代码重用,节约内存空间
何时继承:只要多个子元素公用的属性和【方法】,都应集中在父元素中
js的面向对象是基于原型(父元素)的
原型
保存着一类子对象共有属性和共有方法的原型对象(父元素)
-
如何找到原型对象
-
对象名.__proto__至少要创建一个对象才能使用本方法 -
构造函数名.prototypenew 构造函数(Object/RegExp/Date/Function/String/Number)
-
-
在原型对象中添加共有属性和共有方法
原型对象.属性名=属性值;原型对象.方法名=function(){}-
每个对象都有一个
.__proto__的属性指向着自己的原型 -
每个构造函数都有一个
.prototype属性指向自己的原型
-
-
原型链: 自己没有的属性和方法,可以顺着原型链向上找,直到最顶层(Object.prototype)
- 作用:查找属性和方法
-
自有和共有
-
自有:保存在对象本地
-
共有:保存在原型对象中,子对象都可以直接使用
-
常见问题
1.判断一个属性是自有还是共有
自有
obj.hasOwenPrototype("属性名");
true -> 自有; false -> 可能共有,也可能没有
共有: 2个条件
obj.hasOwenPrototype("属性名")==false;//判断不是自己
"属性名"in obj;//in关键字会查找自己的原型
//判断自有、共有
if(obj.hasOwenPrototype("属性名")){
console.log("自有");
}else{
if(obj.hasOwenPrototype("属性名")=false&&"属性名" in obj){
console.log("共有");
}ekse{
console.log("没有");
}
}
2.修改/删除属性
自有
修改 obj.属性名=新值;
删除 `delete obj.属性名;
共有: 找到原型再做操作
修改:不要在本地做操作,会导致在本地添加上一个同名属性,优先使用自己的,但没有修改原型
删除:不要再本地做操作,本地操作无效果
3.为一类人添加方法
//为老IE数组添加indexOf方法
if(Array.prototype.indexOf===undefined){
Array.prototype.indexOf=function(key,starti){
starti===undefined&&(starti=0);//设置默认值
for(var i=starti;i<this.length;i++){
if(this[i]==key){
return i;
}
}
return -1;
}
}
4.判断x是否是数组
方法1
判断当前对象是否是继承自Array.prototype
Array.prototype.isPrototype(x);也可以判断其他类型
true:数组
方法2
判断当前对象是否是由此构造函数创建
x instanceof Array;也可判断其他类型
true:数组
方法3
Array.isArray(x);只有数组有这个方法
true:数组
方法4
使用多态来判断x是否是一个数组:在Object的prototype中保存着最原始的toString方法
原始的toString输出的结果:[object 构造函数名]
if(Object.prototype.toString.apply(arr)==="[object Array]"){
数组
}
多态: 子对象觉得父对象提供的方法不好用,可在本地定义一个同名成员,有限使用离自己更近的方法(同一函数名,但不是同一个方法)
5.如何设置自定义继承
-
设置单个对象的继承:
obj.__proto__=新对象; -
设置多个对象的继承:(创建对象前要设置好父对象)
构造函数名.prototype=新对象;
两链一包
闭包 保护一个可以【反复使用的局部变量】的一种词法结构
作用:结合全局和局部的优点
作用域链 以EC中的scope chain属性为起点,经过AO逐级隐痛,形成的一条链式结构
作用域链:查找变量
原型链 自己没有的属性和方法,可以顺着原型链向上找至最顶层(Object.prototype)
原型链作用:查找属性和方法