JavaScript从零开始,第三周学习内容回顾

149 阅读9分钟

正则表达式

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

   语法:
    /正则表达式/

1.最简单的正则:关键字原文'no' /no/后缀

  后缀:   g:global 找全部
           i:忽略大小写

2.备选字符集:/^[备选字符集]$/

 强调: 1.一个中括号,只管一位字符
       2.正则表达式默认只要满足就不管后续,我们希望从头到尾完全匹配,解决:前加^后加$
       /^[备选字符集]$/
 特殊:
     如果备选字符集中的ASCII码是连续的
 比如:
     一位数字:[0-9]
     一位字母:[A-Za-z];
     一位字母、数字、下划线:[0-9A-Za-z_]
     一位汉字:[\u4e00-\u9fa5]

预定义字符集:简化备用字符集

一位数字:\d  ===  [0-9]
一位字母、数字、下划线:\w  ===[0-9A-Za-z_]
一位空白字符:\s  包括:空格、制表符、换行
一位除了换行外的任意字符: .   很少使用范围太广
    优先使用预定义字符集,预定义满足不了在备选自定义补充
    不管是预定义字符集还是备选字符集,一个都只管一位

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

1.有明确的的数量

字符集{n,m}:前面相邻的字符集至少n个,最多m个
字符集{n,}:前边相邻的字符集至少n个,多了不限
字符集{n}:必须n个

2.没有明确的数量

?:前边相邻的字符集,可有可无,最多1个
*:前边相邻的字符集,可有可无,多了不限
+:前边相邻的字符集,至少1个,多少不限

选择和分组

选择:在两个规则中选一个
    规则1 | 规则2
分组:将多个字符集临时组成一组子规则
    (规则1 | 规则2)

制定匹配位置

^:开头
$:结尾
特殊:两者同时使用,前加 ^ 后加 $ 表示从头到尾要求完全匹配--只需要做验证

密码强度:4位密码,数字和字母的组合,至少出现一位数字和一位大写字母

/^[0-9A-Za-z]{4}&/  4位密码,数字和字母的组合,至少出现一位数字和一位大写字母
预判公式:(?![0-9]+$)--不能有数字组成
         (?![a-z]+$)--不能由小写字母组成
         (?![0-9a-z]+$)--不能全由数字小写字母,不嫩只有它两的组合组成
         /(?![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位密码,数字和字母的组合,三者必须都有

支持正则表达式的字符串的API

1、切割:var arr=str.split(reg)

2、替换:

            1、基本替换法:缺陷:替换的新东西是固定的
		var newStr=str.replace(/正则表达式/后缀,"新内容");
		//replace支持正则,并且搭配上后缀就可以找到全部

	2、高级替换法:
		var newStr=str.replace(/正则表达式/后缀,function(a){
			//a代表正则匹配到的当前的关键字
			return a.length==2?"**":"***";
		});

	3、格式化:
		var id="500103198602215933";
		var reg=/\d{6}(\d{4})(\d{2})(\d{2})\d{4}/;
		id=id.replace(reg,function(a,b,c,d){
			//在replace的时候,正则出现了分组:我们会得到更多的形参
			//在形参a的后面就会出现n个形参,就看你有多少个分组
			//第一个分组获得的内容会保存在第二个形参中
			//第二个分组获得的内容会保存在第三个形参中
			//...
			return b+"年"+c+"月"+d+"日";
		})
		console.log(id);

3、正则对象:

       创建:
            直接量方式:var reg=/正则表达式/后缀;
            构造函数方式:var reg=new RegExp("正则表达式","后缀");

       API:var bool=reg.test(用户输入的内容);
            true->验证成功 false->验证失败

Math:提供了数学计算的API

1、属性:Math.PI===3.1415926 浏览器自带

2、API:

            1、取整:
		上取整:Math.ceil(num);
		下取整:Math.floor(num);
		四舍五入:Math.round(num);
		*parseInt/parseFloat/num.toFixed(d);

	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);

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、两个日期可以相减,得到的毫秒差,换算出自己想要的部分
          var date = new Date(毫秒数)
  2、API:分量:*FullYear Month Date Day Hours Minutes Seconds
	  每一个分量都有一对儿get/set方法,除了Day没有set

	  获取:date.getXXXX();
	  设置:date.setXXXX(date.getXXXX()+/-num);
  3、格式化为本地格式字符串:date.toLocaleString(); - 具有兼容性问题
    取值范围:
        Full Year:当前年份的数字
        Month0~11
        Date: 1-31
        Day0-6在外国人的眼里星期天才是一周的第一天
        Hours:0-23
        Minutes.Seconds:0-59

Error对象

1、浏览器自带4种错误类型:

        SyntaxError - 语法错误,标点符号的问题
	TypeError - 类型错误,用到别人的方法了
	ReferenceError - 引用错误,没有创建
	RangeError - 范围错误,num.toFixed(d);//0-100之间

2、抛出自定义错误:throw new Error("自定义错误信息");

3、只要是报错就会导致后续代码被打断 - 错误处理

        try{
		可能出错误的代码
	}catch(err){
		console.log(err);//给出了错误的提示,不会影响后续代码
	}

	优先使用:if...else - 主要:以正则来规定用户只能输入什么

Function:

1、创建:var 函数名=new Function("形参",...,"函数体;return 返回值");

2、重载:同一个函数名,传入的实参的不同(长度或类型),自动选择对应的操作执行 arguments对象 - 类数组对象:接住所有的实参 变相实现我们的重载操作:

3、匿名函数:

   1、自调:只会执行一次,代替全局写法,自动释放所有无用的内存(变量)
		(function(){
			//操作
		})();

2、回调:多半都是前辈们提供好了,我们学习的固定用法,在一个函数中传入的实参又是一个匿名函数,而且不需要我们调用非
		arr.sort(function(a,b){return a-b})
认识了哪些叫做回调函数,只要没有名字,只要没有自调,一定就是回调 - 以后简化为箭头函数

Function:

函数的执行原理:才有变量的使用规则,优先使用自己,没有找全局,全局没有则报错,才知道了为什么函数中的东西会自动释放

作用域链:以函数的EC为起点,经过AO,逐级引用形成的链式结构,作用上面那句话

闭包:

保护一个可以反复使用的局部变量的一种词法结构

如何使用:

     1.两个函数进行嵌套
     2.外层创建出受保护的变量
     3.外层函数return出内层函数
     4,。内层函数要去操作受保护的变量
     
     function outer(){
	受保护的变量
	return function(){
		操作受保护的变量
	}
 }

 缺点:用多了,会导致内存泄漏

强调

1.判断是不是闭包,有没有两个函数嵌套,返回内层函数内层函数在操作受保护的变量
2.外层函数调用了几次,就创建了几个闭包,受保护的变量就有了几个副本
3.同一次外层函数调用,返回的内层函数,都是操作同一个受保护的变量

缺点

受保护的变量用户按都不会被释放,使用过多内存泄漏---不可多用

使用场景:防抖节流(mousemove、input、resize)

问题:应该在哪里用呢?
		1、三个事件需要防抖节流
			1、elem.onmousemove - 鼠标移动事件
			2、input.oninput - 每次输入/改变就会触发
			3window.onresize - 每次窗口的大小发生变化就会触发

		  	
		防抖节流公式:
			elem.on需要防抖节流的事件=function(){
				fdjl();//内层函数只要一旦移动就会触发
			}

			function f1(){
				var timer=null;//3
				return function(){//
					if(timer){clearTimeout(timer);timer=null;}
					timer=setTimeout(function(){
						//操作
					},1000)
				}
			} 
			
			var fdjl=f1();

Object 面向对象:封装:

面向对象:三大特点:封装、继承、多态

1、直接量:

             var obj={
			属性名:属性值,
			...
			方法名:function(){
				操作
			},
			...
		   }

2、预定义构造函数:var obj=new Object();

3、多个对象创建:自定义构造函数

            1、创建构造函数
		function 类名(形参1,形参2){
			this.属性名=形参1;
			this.属性名=形参2;
		}

	2、使用构造函数创建对象
		var obj=new 类名(实参1,实参2);
难点:
                this的指向:
			1、单个元素绑定事件:this->单个元素
			2、多个元素绑定事件:this->当前触发的元素
			3、函数中使用thisthis->谁在调用此方法,this指的就是谁
			4、定时器中this->window

4、使用:

                obj.属性名;
		obj.方法名();
		遍历:for in

		在方法中想要使用对象自己的属性要写为:this.属性名;

Object继承

1、父对象的成员(属性和方法),子对象可以直接使用

 为什么:代码重用!节约内存空间!提升网站性能!
 何时继承:只要多个子对象公用的属性和方法,都要集中定义在父对象中
 

2、如何找到父对象(原型对象):保存一类子对象共有属性和共有方法的父对象

1、对象名.__proto__;     //必须先有一个对象
2、构造函数名.prototype;     //构造函数名,几乎人人都有,除了Math

3、两链一包:作用域链、原型链、闭包

每个对象都有一个属性:__proto__,可以一层一层的找到每个人的父亲,形参的一条链式结构,就称之为叫做原型链
可以找到所有父对象的成员(属性和方法),作用:找共有属性和共有方法的
最顶层是Object的原型,上面放着我们一个眼熟的toString,怪不得人人都可以用到toString();
JS万物皆对象

4、有了原型对象,设置共有的属性和方法:

1、原型对象.属性名=属性值;    //添加了一个共有属性
2、原型对象.方法名=function(){};    //添加了一个共有方法

5、理论题:

    1、判断是自有还是共有:
		1、判断自有:obj.hasOwnProperty("属性名");
			如果结果为true,说明是自有属性,如果结果为false,有两种可能,共有或没有
		2、判断共有:
			if(obj.hasOwnProperty("属性名")==false && "属性名" in obj){//in 会自动在obj的原型上进行查找
				共有
			}else{
				没有
			}

		公式:
		if(obj.hasOwnProperty("属性名")){//false
			console.log("自有")
		}else{  
			if("属性名" in obj){
				console.log("共有")
			}else{
				console.log("没有")
			}
		}

	2、删除自有和共有
		自有:修改:obj.属性名=新值;
		      删除:delete obj.属性名;

		共有:修改: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;
			}
		}

	
	4、如何判断x是不是一个正则:4种方法:千万别用typeof,只能检查原始类型,不能检查引用类型
		1、判断x是否继承自Array.prototype
			Array.prototype.isPrototypeOf(x);

		2、判断x是不是由Array这个构造函数创建
			x instanceof Array;

		3Array.isArray(x); - ES5提供的,只是ES5+,老IE不支持,此方法只有数组

		4、输出【对象的字符串】形式
		   在Object的原型上保存着最原始的toString方法
		   原始的toString输出形式:[object 构造函数名]
		   ***多态:子对象觉得父对象的成员不好,在本地定义了同名成员,覆盖了父对象的成员
		   固定套路:借用:Object.prototype.toString.apply(x);
			if(Object.prototype.toString.apply(arr)=="[object Array]"){
				console.log("是数组")
			}else{
				console.log("不是数组")
			}

	5、实现自定义继承:
		1、两个对象之间设置继承:
			子对象.__proto__=父对象
		
		2、多个对象之间设置继承:
			构造函数名.prototype=父对象
			时机:应该在开始创建对象之前设置好继承关系