JAVAscript小结(三)

140 阅读16分钟

*****正则表达式

什么是正则表达:定义字符串中【字符出现规则】的表达式
如何定义正则表达式:

1.语法:

/正则表达式/

2.最简单的正则:

关键字原文本身:"no" /no/ig
          i:忽略大小写
          g:全部

3.备选字符集:

一个备选字符集:规定了【一位】字符可用的备选字符列表
   如何:/[备选字符集列表]/
   强调:1.一个中括号,只能匹配以为字符
         2.正则默认只要满足后,就不再管后续操作,后续用户可以乱输入-不合理 
        解决:只要是做验证!!!必须/^[备选字符集]$/,前加……后加¥代表要从头到尾完全匹配-用户输入的东西必须和我规定的东西一样
        特殊:1.如果备选字符集中,unicode好事连续,那么中间部分可以用-代替
        比如:一位数字:[0-9]
              一位字母:[A-Za-z]
              一位汉字:[\u4e00-\u9fa5]
         2.除了XXX之外,其它都是可以:-很少使用,范围太广了
         [^xxx]
         [^0-9]
         3.预定义字符集:前辈们提供好了一些常用的字符集的简化写法:
         一位数字'\d  ==>[0-9]
         一位数字、字母、下划线、:\w ==>[0-9A-Za-z]
         一位除了换行外的任意字符集,如果预定义字符集没有,在用备选字符集补充
         强调:不管是备选字符集还是预定以字符集,一个都只管一位

4.量词:规定了一个字符集出现的次数

1.有明确的数量
    字符集{n,m}:前边相邻的字符集,最少出现n次,最多出现m次
    字符集{n,}:前边相邻的字符集,最少出现n 次,多了不限
     字符集{n}:前边相邻的字符集,必须出现n次
 2.没有明确数量
     字符集?:前边相邻的字符集,可有可无,最多一次
     字符集*:前边相邻的字符集,可有可无,多了不限
     字符集+:前边相邻的字符集,至少一次,多了不限

5.指定匹配的位置

 ^:以XX开头
 $:XXX结尾
 特殊:如果^和$同时出现:前面加^后加$,代表要求从头到尾完全匹配-只要事做验证必须加

6.选择和分组

选择:规则1|规则2-可以在多个规则中选择满足的规则进行执行
分组:添加子规则:(规则1|规则2)

7.预判:密码强度:2-4位字母和数字的组合,至少一位大写字母和一位数字

公式:
(?![0-9]+$)字符集量词 --不能全由数字组成
(?![0-9A-Z]+$)字符集量词 --不能全由数字组成不能全又要大写组成,不能全由数字和带小额的组合组成
(?![a-z0-9]+$)(?![a-zA-Z]+$)(?![0-9A-Z]+$)(0-9A-Za-z){24}--
                不能是纯数字、纯大写、纯小写
                也不能是小写和数字的组合
                也不能是小写和大写的组合
                也不能是数字和大写的组合
          

2.字符串中支持正则表达式的API:分割、替换 分割字符串: var arr=str.split(teg); *****替换字符串

 1.基本替换法:
     var newStr=str.reolace(reg,"新内容");
     特殊:1.默认只会替换第一个关键字,想要替换所有的内容只能是一个固定的新内容
  2.高级替换法
      var newStr=str.replace(/[内容1][内容2]+/g,function)(a,b,c){
    console.log(a);//正则匹配到的关键字
console.log(b);//正则匹配到的关键字的下标
console.log(c);//原文本身
return a.length==2?"**":"***";
}
  3.格式化:如果替换API使用正则时,并且里面带有分组,那么你会得到更多的形参
   varnewStr=str.replace(reg,function(a,b,c...)
   console.log(a);//正则匹配到的关键字
   console.log(b);//第一个分组获取到的内容
   console.log(c);//第二个分组获取到的内容
   return "格式化的东西"
		});
 出现在:面试题中

3.正则对象:

创建正则对象:2个
直接量:var reg=/正则表达式/后缀
构造函数: var reg=new RegExp("正则表达式","后缀");
 方法:var bool=reg.test(user);
 布尔值如果是true,说明用户输入的符合我们的要求,false说明不通过
 

Math:专门提供了数字计算的API

强调:不能创建,不需要创建,直接使用!
   唯一的属性:Math.PI

API:

1.取整:3种
上去整:只要超过一点点。就会取下一个整数,此方法小数位数不能超过15位否则会失效:Math.ceil(num);
下取整:不管超过多少,都会省略掉小数部分,此方法小数位数不能超过15位否则会失效:Math.floor(num);
四舍五入取整:
    Math.round(num);
问题:帮的:parseFloat(num.toFixed(d));//既有四舍五入功能,又具有保留自定义小数位数的操作,结结果是一个字符串
笔试题:*封装一个函数,实现可以自定义保留小数位数并且四舍五入的功能,但是不允许使用toFixed?
function round(num,d){			num*=Math.pow(10,d);
num=Math.round(num)
num/=Math.pow(10,d);
return num.toString();
}
    
2.乘方和开方
    *乘方:Math.pow(底数,幂);-简化连续的乘法
    开方:Math.sqrt(num); -只能开平方
3.最大值和最小值
    语法:Math.max/min(a,b,c,d,e,f,……);
    获取到最大的一个数或者是最下的一个数
    问题:不支持数组参数
    *解决:Math.max/min.apply(Math,arr);
            apply:直接没有的方法可以去借用
            可以将数组打散为单个参数悄悄进行传入
 4.绝对值:将负数转为整数
     Math.abs(num);
 5.**随机数:只要页面上具有随机的功能,底层一定用到了随机数
 Math.random()已经是一个随机数了,随机的小数0-1;有可能取到0,但是绝不可能取到1--意味着能取到最小值,但是取不到最大值
     公式:parselnt(Math.random()*(max-min+1)+min);

2.Date:封装了一个日期对象,提供了对日期事件进行操作的API

何时使用:以后只要网页上跟日期事件相关的,我们都要使用date对象
1.创建日期对象:4种
    1.创建当前时间:
    var now=new Date();
    2.闯将自定义时间
    var birth=new Date("yyy/MM/dd hh:mm:ss");
    3.创建自定义时间
    var birth=new Date(yyy.MM.dd,hh.mm,ss);
    4.复制一个日期对象
    为什么:日期对象的API都是 直接修改原日期对象,使用API后,无法同时保存住旧的日期对象
    何时使用:在调用日期对象的API之前只要先复制,在使用API
    语法:var end=new Date(now);
     5.var xx=new Date(毫秒数);
     计算器其实保存的即使从1970年1月1日至今的毫秒数

2.操作

1.俩个日期对象之间可以相减,得到毫秒差,换算出你想要的任何一部分,看出细节其实日期对象保存的就是一个毫秒数
2.API
 分量:时间单位
 FullYear Month Date Day
 Hours Minutes Seconds
 1、每一个分量都有一对儿方法getXXX()/setXXX()
特殊:1、取值范围:
年:当前年份
月:0-11
日:1-31
时:0-23
分:0-59
星期:0-60代表星期天
   2、星期只有get,没有set

2.固定套路:对着某个日期直接做加减

      date.setxxx(date.getxxx()+3)

3.格式化为字符串:

      国际化日期格式化为本地化日期:date.toLocaleString();-垃圾
      1.具有浏览器的兼容性问题
      2.则不可以在使用日期对象的API,也不会在带有进制操作了
      好处:转为了字符串可以用字符的API
          解决:自定义format格式化
          
          
          
          

Error:错误对象

 1*浏览器自带4种错误类型
   语法错误:SyntaxError -对半是哪里的符号写错了
   引用错误:ReferenceError -根本就没有创建过,就去使用了
   类型错误:TypeError -不是你的方法,你却使用了
   范围错误:RangeError -只有一个API :num.toFixed(d);//d的范围只是1-100之间
   记住这些能快速帮助我们找到错误的地方
  2.错误处理:当程序发生错误时,保证程序不会异常中断的机制
  为社么:只要报错,就会导致后续代码终止(闪退),用户体验感降低
  如何解决:try...catch..语句
   try{
	可能出错的代码
    }catch(err){
	console.log(err);//提示用户错误的原因是什么
    }
        后续代码都可以执行到
    不推荐:try..catch...的执行效率非常的低下,更推荐的时if..else
    想要用if...else去预判用户的错误的前提:丰富的经验
   3.抛出自定义错误:
   throw new Error("自定义错误信息");

2.*****Funcion:函数对象-方法

创建:31.声明方式
      var 函数名=function(形参列表){函数体;return 结果;}
      具有完整阿声明提前
   2.直接方式
       var 函数名=function(形参列表){函数体;return 结果;}
       也有声明提前,但是赋值留在原地
   3.构造函数方式-函数体不是固定的
   var 函数名=new Function("形参1","形参2",...,"函数体");
   函数体时动态拼接时候,注意不能省略""部分
  调用:
  函数名();
  元素.noclick();
  
  考点:
  1.***创建
  2.***作用域:全局(成员哪里都是可以使用)、函数(成员只能在函数调用时内部可用)
   变量的使用规则:优先使用局部的,局部没有找全局,全局没有就报错
   3.***声明提前:在程序正式执行之前,会将var声明的变量和function声明的函数集中提前到当前作用域的顶部,但是赋值留在原地,变量比函数轻
   4.***按值传递:如果传递的时原始类型,互不影响。如果传递的时引用类型,相互影响。
   5.***重载:相同的函数,根据传入的实参的不同,会自动选择对应的函数执行
   为什么:减少程序员的负担
   问题:JS不允许同时存在多个同名函数,如果存在,最后的一个会覆盖之前的所有函数
   解决:arguments对象-只能在函数内部可用,时一个类书组对象;
   作用:按在所有的实参,【以后甚至不用形参都可以】
   只有3点相同:
       1.支持下标
       2.支持length
       3.支持遍历
     变相实现重载:通过判断arguments的不同,执行不同的操作
     6***匿名函数
     没有名字的函数,没有变量名/函数名引用着,调用一次完毕后会立马释放,-一次性函数
      21.匿名函数自调:代替全局作用域
      (function(){
	函数体; - 好处:调用完毕会【立刻释放】
})()
       2.匿名函数回调:某个函数调用时,传入的实参又是一个函数,而且不需要我们调用自动执行
       比如:
        arr.sort(function(a,b){return a-b})
        str.replace(reg,function(){})
***你要认识什么叫做回调函数:
匿名函数,不是自调,就一定是回调 - 以后会学习箭头函数:简化一切的回调函数 

*****Function

*****闭包

作用域:2种

   1.全局作用域:成员随处可以用,可以反复使用,容易被污染
   2.函数作用域:成员只有当前函数调用时内部可用,调用完了,就会释放了,一次性

***函数的执行原理:

1.程序加载时

   创建执行环境栈(ECS):保存函数调用顺序的数组
   首先压入全局执行环境(全局EC)
   全局EC引用着全局对象window
   window种保存着全局变量

2.定义函数时

    创建函数对象封装函数的定义
    在函数对象种创建scope属性,记录自己来自的作用域
    全局函数的scope都是window

3.调用函数前

     在执行环境栈ECS压入新的函数的EC
     创建活动对象AO:保存着本次函数调用时的用到的局部变量
     在EC中添加scope chain属性引用AO
     设置AO的parent属性为函数的scope引用的对象

以上3条文字画图如下:

无标题.png

4.调用时

      变量的使用规则:优先使用局部的,局部没有才找全局,全局没有才报错

5.调用完

 函数的EC会出栈,AO会自动释放,局部变量也就自动释放了
 

***面试:作用域链scope chain:

  以EC中的scope chain属性为起点,经过AO逐级引用,形成的一条链式结构,就称只为叫做作用域链
  作用:查找变量

*****闭包:目的:保护一个可用【反复使用的局部变量】的一种词法结构结合了全局和局部的有点

 唯一的缺点:受保护的变量永远不能释放,用多了会导致内存泄漏
 尽量的少用:只有一个点会用到防抖节流
 如何:3种
     1.创建一个外层函数
     2.在其中创建一个受保护的局部变量
     3.外层函数调用要返回内层函数,此内层函数在操作受保护的变量
   
   

笔试时

  1.判断闭包,找到受保护的变量,确定其值
  2.外层函数调用几次,就创建几个闭包,受保护的变量就有了几个副本
  3.同一次外层函数调用,返回的内层函数,都是在使用同样一个同一个受保护的变量
  

固定语法:

    function 外层函数(){
受保护的变量;
return function(){
不断的操作受保护的变量
return 结果;
}
}	
var 内层函数=外层函数();
正式开发:防抖节流:减少DOM树的渲染,DOM数据渲染的次数越频繁页面的效率越底下

3个事件需要去做防抖节流:

    1、elem.onmousemove - 鼠标移动事件,每次移动就会触发
    2、input.oninput - input每次修改内容就会触发
3window.onresize - 屏幕每次改变大小就会触发
固定公式:
function fdjl(){
var timer=null;//3
return function(){//判断有没有定时器,如果有定时器就清除定时器
if(timer){clearTimeout(timer)}		timer=setTimeout(function(){//你要做的操作},毫秒数)					console.log(timer);//定时器的序号
}
}
var animate=fdjl(); 

2.*****Object:面向对象开发方式-三大特点(封装、继承、多态)

   什么是面向对象:在程序中都使用对象来描述现实中的一个事物
   现实中事物的属性,代码中就成为了对象的属性
   现实中所有数据都必须包含在一个事物中才具体的意义

1.封装/创建/定义/声明/实列化:自定义创建对象:3种

 1.*直接量方式:
     var obj={
          "属性名":属性值,
         ...
         "方法名":function(){},
   强调:1.其实属性名和方法名的“”可以省略,但是不推荐,以后JSON必须加""
         2.如何访问对象属性和方法
             obj.属性名===obj["属性名"]
             obj.方法名();===obj["方法名()"]
          3.访问到不存在的属性:返回undefined
          4.也可在后续随时随地的添加自己想要的东西
          
      特俗:this在当前对象的方法内,指向的当前调用方法对象
      面试题:this指向
      1.单个元素绑定事件 this-->单个元素
      2.多个元素绑定事件 this -->当前出发的元素
      3.函数中也可以使用 this-->当前调用函数的对象
      4.构造函数中如果出现了this this ->当前正在创建的对象
    只要以后对象那个的方法想要使用对象自己的属性,那么就写为this.属性名
 2.预定义构造函数:var obj=new object();//空对象    
 obj.属性名=属性值;
...
 obj.方法名=function(){}
...
    以上两个方法仅适合创建单个对象,如果想要创建多个对象则太繁琐
 3、*自定义构造函数:21、创建一个构造函数
function 类名(形参,...){
        this.属性名=形参1;
        this.属性名=形参2;
	...
	}

2、反复调用构造函数创建出多个对象
        var xxx=new 类名(实参,...)   

面试:聊一聊你了解面向对象和面向过程的开发方式?

    1、面向过程:开始->经过->结束,我们一直使用的开发方式。
 2、面向对象:对象:属性和方法   
     所有的属性和方法全都是包含在一个对象中的,比如:轮播对象、选项卡对象...
    优:1、逼格高
        2.所有的操作都包含在一个对象中,显得更有意义
        3.维护是非常的舒服
        4.铁锁链舟 - 一个方法调用,出发了一大堆操作
     缺:1.难度大 -this的指向
     

*****面向对象

*****继承:父对象的成员(属性和方法):子对象可以直接使用

为什么继承:代码重用!节约内存空间!
何时继承:只要多个子对象公用的属性和【方法】,都应该集中定义在父对象那个中
JS的面向对象是基于原型(父对象那个)的
什么是原型:白村一类对想共有方法的原型对象(父对象)
1.如何去找到原型对象
    1.对象名.__proto__-至少要创建一个对对象才可以使用
    2.构造函数名.prototype
    new 构造函数 (Object RegEp Date Function Sting 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;
    }
}
      比如:为一人添加共有方法
  构造函数名.protot.函数=function(){
this->函数中的代表当前调用此函数的对象
}

4、判断x是不是一个数组:4种

 1、判断当前x对象是否是继承自Array.prototypeArray.prototype.isPrototypeOf(x);
true说明是一个数组
  2、判断当前x对象是否是由此构造函数所创建
x instanceof Array
true说明是一个数组
  3Array.isArray(x); - 只有数组才有此方法
     true说明是一个数组
  4、最麻烦,但是我个人最喜欢
      在Object的prototype中保存着最原始的toString方法
    原始的toString输出的结果:[object 构造函数名]  
  ***多态:子对象觉得父对象提供的方法不好用,可以再本地定义一个同名成员,优先使用离自己更近的方法
      同一个函数名,但根本不是同一个方法
	   固定套路:
       
       if(Object.prototype.toString.apply(arr)==="[object Array]"){
       数组;
     }

5.如何设置自定义继承

       设置自定义继承:
           obj.__proto__新对象
        设置多个对象的继承
            构造函数名.prototype=新值
            注意时机:在创建对象之前就设置好父对象