一、正则表达式
分割、替换、验证:
目的:会看、会改、会答
1、正则表达式:
1、最简单的正则:/原文/后缀ig
2、规定一位字符可能出现的情况:备选字符集 /[0-9]/
3、预定义字符集: \d - 一位数字 \w - 一位数字、字母、下划线 \s - 一位空白字符 . - 除了换行外的任意字符
4、量词: {n,m} - 最少n次,最多m次 {n,} - 最少n次,多了不限 {n} - 只能n次
+ - 至少一次,多了不限
* - 可有可无,多了不限
? - 可有可无,最多一次
5、指定位置 ^ $ 特殊:两者同时使用,代表从头到尾完全匹配 - 验证
6、选择和分组 (规则1|规则2)
7、预判的公式: (?!\s+$)
二、字符串中支持正则的API:
var newStr=str.replace(reg,"新内容");
var newStr=str.replace(reg,function(a){
//a:当前正则匹配到的关键字
});
格式化:正则中带有分组 var newStr=str.replace(reg,function(a,b,c...){ //a:当前正则匹配到的关键字 //b:第一个分组获取到的内容 ... });
切割:var arr=str.split(reg);
三、创建正则对象:2种
1、直接量:var reg=/正则表达式/后缀
2、构造函数:var reg=new RegExp("正则表达式","后缀")
方法:验证:var bool=reg.test(user);
1、Math:数学计算,不允许创建,自带
属性:Math.PI
API: 1、取整: Math.ceil(num); Math.floor(num); Math.round(num);
2、乘方:Math.pow(底数,幂);
开方:Math.sqrt(num);
3、最大值和最小值
Math.max/min(a,b,c,d,e...);
支持数组:Math.max/min.apply(Math,arr);
4、绝对值:Math.abs(num);
5、随机整数:parseInt(Math.random()*(max-min+1)+min);
2、Date:创建日期,操作日期的API
创建:
1、当前时间:var now=new Date();
2、自定义时间:var date=new Date("yyyy/MM/dd hh:mm:ss");
var date=new Date(yyyy,MM-1,dd,hh,mm,ss);
3、复制日期:var end=new Date(start);
操作:
1、两个日期可以相减,得到的毫秒差可以换算出你想要的分量
2、FullYear Month Date Day Hours Minutes Seconds
每一个分量都有一对儿getXXX/setXXX,除了Day没有set操作
为某个分量做+或-
date.setXXX(date.getXXX+/-n);
3、格式化:date.toLocaleString();//带有兼容性问题,最好还是自定义format方法
3、Number:
创建:var num=new Number();
num.toFixed(d);//结果是一个字符串
num.toString();
4、Boolean:
创建:var bool=new Boolean();
一切的引用类型的对象,都具有属性和方法:创建的底层都是一个构造函数,直接量都是后续添加上,除了Math不能创建
1、Error
1、浏览器自带 4种错误类型:
1、语法错误:SyntaxError - 符号错了
2、引用错误:ReferenceError - 没有创建
3、类型错误:TypeError - 不是你的方法你却去使用了
4、范围错误:RangeError - num.toFixed(d);//d 0-100之间
2、抛出自定义错误:
throw new Error("错误信息");
3、错误处理:希望不要报错,而是给一个错误提示,不会打断后续代码
try{
可能出错的代码
}catch(err){
console.log("错误提示");
}
还不如用if...else提前的预判 - 规定用户只能输入什么(!isNaN、正则、控制范围)
2、Function
创建:构造函数:var 函数名=new Function("形参1","形参2",...,"函数体;return 结果");
重载:同一个函数名,根据传入的实参的不同,执行对应的函数
arguments类数组对象:哪怕没有形参,接住所有的实参
arguments[0] - 第一个实参
arguments[1] - 第二个实参
...
function f1(){
if(arguments.length==1){
}else if(arguments.length==2){
}...
}
匿名函数:只会使用一次就会自动释放,因为没有函数名/变量名,没有变量引用着的引用类型对象会被垃圾回收器立刻释放
1、自调:代替全局作用域
(function(){
开始写自己的代码 - 变量会自动释放
})();
2、回调:多半都是API里前辈提供好的,我们学习了就可以直接使用,以后回调函数可以简化箭头函数
只要匿名函数,不是自调,一定就是回调
arr.sort(function(a,b){return a-b})
elem.onclick=function(){}
1、Function的闭包:
目的:保护一个可以【反复使用的局部变量】的一种词法结构
语法:
function outer(){
受保护的变量
return function(){
操作受保护的变量
}
}
var 内层函数=outer();
使用场景:防抖节流
function outer(){
var timer=null;
return function(){
if(timer){clearTimeout(timer)}
timer=setTimeout(function(){
操作
},间隔毫秒数)
}
}
var xx=outer();
elem.onmousemove/input.oninput/window.onresize=function(){
xx();
}
2、Object面向对象三大特点:
一、封装
1、*直接量:使用创建单个对象
var obj={
"属性名":属性值,
...
"方法名":function(){},
...
}
2、预定义构造函数:
var obj=new Object();//空对象
追加属性和方法
obj.属性名=属性值
obj.方法名=function(){}
3、自定义构造函数:创建多个对象
1、创建构造函数
function 构造函数名(xingming,nianling,aihao){
this.name=xingming;//ljb.name="";
this.age=nianling;//ljb.age=50;
this.hobby=aihao;//ljb.hobby=3500;
}
2、反复调用构造函数创建对象
var ljb=new 构造函数名("廖家兵",50,3500);
4、访问:
obj.属性名;
obj.方法名();
5、**遍历对象**
for(var i in obj){
obj[i];
}
6、**this的指向**:
1、事件中:单个元素 this->这个元素
多个元素 this->当前触发元素
2、函数中:this->当前调用次函数的人
3、构造函数中:this->当前正在创建的对象
4、定时器中:this->window
*****面向对象
*****继承:父对象的成员(属性和方法):子对象可以直接使用
为什么继承:代码重用!节约内存空间!
何时继承:只要多个子对象公用的属性和【方法】,都应该集中定义在父对象中
JS的面向对象是基于原型(父对象)的
什么是原型:保存一类子对象共有属性和共有方法的原型对象(父对象)
1**、**如何去找到原型对象:
1、对象名.__proto__ - 至少要创建一个对象才可以使用
2、构造函数名.prototype
new 构造函数(Object RegExp Date Function String Number Boolean...)
2、在原型对象中添加共有属性和共有方法
原型对象.属性名=属性值
原型对象.方法名=function(){}
每一个对象都有一个.__proto__的属性指向着自己的原型
每一个构造函数都有一个.prototype属性指向着自己的原型
面试题:两链一包:
原型链:自己没有的属性和方法,可以顺着原型链一直向上找,直到最顶层:Object.prototype - 万物皆对象
作用:查找属性和方法
**自有和共有**
自有:保存在对象本地的
共有:保存在原型对象中的,子对象都可以直接使用
一大批鄙视题:
1、判断一个属性是自有还是共有:
1、判断自有:obj.hasOwnProperty("属性名");
如果结果为true,说明是自有
如果结果为false,可能是共有也可能是没有
2、判断共有:2个条件
obj.hasOwnProperty("属性名")==false;//可能是共有也可能是没有
"属性名" in obj;//in关键字会查找自己的原型
if(obj.hasOwnProperty("属性名")==false && "属性名" in obj){
console.log("共有")
}else{
console.log("没有")
}
完整的:
if(obj.hasOwnProperty("属性名")){
console.log("自有");
}else{
if(obj.hasOwnProperty("属性名")==false && "属性名" in obj){
console.log("共有")
}else{
console.log("没有")
}
}
2、修改/删除属性
自有:修改:obj.属性名=新值;
删除:delete obj.属性名;
共有:修改:千万不要在本地做操作,那会导致在本地添加上一个同名属性,优先使用自己的,但并没有修改原型对象
删除:千万不要在本地做操作,那会导致白做没有任何效果
强调:一定要找到原型再做操作
3、为一类人添加方法:
比如:最常见的一道题:为老IE的数组添加indexOf方法 - 原本只有字符串可以使用,是后续升级数组才能使用的
if(Array.prototype.indexOf === undefined){//老IE
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;
}
}
比如:为一人添加共有方法
构造函数名.prototype.函数名=function(){
this->函数中的代表当前调用此函数的对象
}
4、判断x是不是一个数组:4种
1、判断当前x对象是否是继承自Array.prototype的
Array.prototype.isPrototypeOf(x);
true说明是一个数组
2、判断当前x对象是否是由此构造函数所创建
x instanceof Array
true说明是一个数组
3、Array.isArray(x); - 只有数组才有此方法
true说明是一个数组
4、最麻烦,但是我个人最喜欢
在Object的prototype中保存着最原始的toString方法
原始的toString输出的结果:[object 构造函数名]
***多态:子对象觉得父对象提供的方法不好用,可以再本地定义一个同名成员,优先使用离自己更近的方法
同一个函数名,但根本不是同一个方法
固定套路:
if(Object.prototype.toString.apply(arr)==="[object Array]"){
数组
}
5、如何设置自定义继承
设置单个对象的继承:
obj.__proto__=新对象
设置多个对象的继承:
构造函数名.prototype=新对象
注意时机:在创建对象之前就设置好父对象