JavaScript第三周知识点总结

91 阅读4分钟

一. 递归

1.递归简单来说就是函数自调, 循环会停止

2.专门用于【遍历层级不明确的情况】 - DOM树和数据(children只能找到儿子层,找不到孙子层)

3.使用步骤:

    function 函数名(root){
	1、写第一层的操作

	2、判断有没有下一层,有再次调用此方法,传入的实参是自己的下一层		
}
函数名(实际的根)

4.算法: 深度优先!优先遍历当前节点的子节点,子节点遍历完毕才会跳到兄弟节点

5.缺陷: 使用过多会降低浏览器性能同时开启大量的函数调用,浪费内存,只在【层级不明确】时使用

6.递归和纯循环对比

循环方式优点缺点
递归简单易用性能低
纯循环性能高操作语句复杂,写起来相对困难

2.事件的绑定与取消

1.使用elem.on事件名=()=>{}绑定 使用elem.on事件名=null取消

2.使用elem.addEventListener("事件名",回调函数);绑定 使用elem.removeEventListener("事件名",回调函数);来取消,事件名和回调函数必须一一对应

3.this的指向问题

1.this的指向

   单个元素绑定事件this->这个元素
   
   多个元素绑定事件this->当前元素
       
   箭头函数中的this->外部对象
       
***函数中的this->当前正在调用函数的东西

   定时器的this->window

2.强制改变this的指向

 (1) call/apply:临时的替换了函数的this - 借用
	语法:函数名.call(借用的对象,实参,...); - 单独传入每个实参
            
	          函数名.apply(借用的对象,arr); - 只能传入一个实参要求是一个数组,
                                                apply其实会打散数组
                                                
	强调:call/apply:相当于立刻调用函数,立即执行的

 (2)bind:永久替换了函数中的this - 买
 
	1、创建了一个和原函数功能完全相同的新函数
            
	2、将新函数的this永久绑定为了指定对象,不再借出
            
	3、将新函数的部分参数永久固定
            
	语法:var 新函数=函数名.bind(永久对象,永久实参,...); - 不是立刻执行,需要自己调用
	强调:bind绑定的新函数没办法被call/apply再次借走

	三个固定用法:
		1Math.max/min.apply(Math,arr) - 也能支持数组参数
                    
		2Object.prototype.toString.call/apply(x)==="[object Array]";
                    //笔试题:判断x是否是一个数组
                    
		3、类数组转为普通数组:
			1、接住=Array.prototype.slice.call/apply(类数组对象)
			2、接住=Array.from(类数组对象)

4.ES6

1.已学部分: let,const关键字 箭头函数

2.模板字符串:可以直接识别变量,不需要+运算去拼接,而且实现了一个简单的js环境,甚至支持在里面书写API

	`我的名字叫${name}`

3.解构赋值: 解析结构再进行赋值 - 赋值的新方式,并且得到了增强

	如果赋值符号,左右两边的结构一样的,先解开结构再一一赋值
	语法:
		1、类似数组的解构赋值
			let [a,b,c]=[1,2,3];
			console.log(a);
			console.log(b);
			console.log(c);

		2、类似对象的解构赋值
			let {a,b=默认值,c}={c:3,a:1,b:2};
			console.log(a);
			console.log(b);
			console.log(c);
			//形参可以设置默认值,传入了值就覆盖默认值

		3、调用函数时,传入实参的顺序可以改变
			function zwjs({name,age,hobby="女"}){
				return `我的名字叫${name},今年${age}岁,喜欢${hobby}`;
			}
			console.log(zwjs({hobby:"学习",age:18,name:"袍哥"}));

		4、函数的返回的结果,可以有多个
			function f1(){
				var a=1;
				var b=2;
				return [a,b];
			}
			var [a,b]=f1();
			console.log(a,b);

		只要以后见到:方法名({键值对})就是使用了ES6的解构赋值

4.Set和Map - 新的数据类型:

	1、*Set:类似于数组的一种数据格式 - 【去重数组,然后再转回数组】
		var s=new Set(arr);
		...s - 三个点扩展运算符,可以解开数组结构
		一句话完成去重数组并转回数组:
                    [...new Set(arr)] 

	2Map:类似于对象的一种数据格式
		var m=new Map();
		添加:m.set("键","值");
		获取:m.get("键");
		清空:m.clear();
		删除:m.delete("键");

5.新的循环 - 没用

 for(var v of arr){
		v;
	}

缺陷:
	1、没有提供过下标,不能修改原数组
	2、只能遍历索引数组,不能遍历hash数组,也不能遍历对象

5.正则表达式:

定义字符串中字符出现规则的表达式

何时使用:切割 替换 【验证】!

如何使用:语法:/正则表达式/

一.基本属性

1.最简单的正则就是关键字原文 "no" -> /no/后缀

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

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

   强调:
         1. 一个中括号,只管一位字符
         2. 问题:正则表达式默认只要前面几位设置了正则的字符满足就不管后边,
         而我们做验证的人,希望的是用户从头到尾按照我们的要求来,希望从头到尾完全匹配:
         3. 解决:前加^,后加$,两者同时使用,代表要求从头到尾完全匹配/^[备选字符集]$/
             - 只要做验证必加!
         4. 特殊:如果备选字符集中的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、无明确数量:
			字符集?:前边相邻的字符集,可有可无,最多1个
			字符集*:前边相邻的字符集,可有可无,多了不限
			字符集+:前边相邻的字符集,至少一个,多了不限

5.选择和分组:

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

6.指定匹配位置

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

7.密码强度验证:/^[0-9A-Za-z]$/数字,大写,小写

  预判公式:
	(?![0-9]+$) -> 不能全由数字组成,可能有大写、小写、汉字、日文、特殊符号...
            
	(?![a-z]+$) -> 不能全由小写组成,可能有数字、大写、汉字、日文、特殊符号...
            
	(?![0-9a-z]+$) -> 不能全由数字组成、也不能全由小写组成、
                          也不能全由数字和小写的组合组成

  比如:
	/(?![0-9a-z]+$)(?![A-Za-z]+$)[0-9A-Za-z]{2,4}/;
            2-4位,可以输入数字、字母,但是必须出现一位大写和一位数字的组合
            
	/(?![0-9a-z]+$)(?![A-Za-z]+$)(?![A-Z0-9]+$)[0-9A-Za-z]{2,4}/;
            必须三者都有
			
        /(?![0-9A-Za-z]+$)[0-9A-Za-z_]{2,4}/;
        至少要有下划线

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

1.切割:var arr=str.split("固定切割符"/RegExp);

2.*替换:很有可能出现在笔试之中

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

  2、高级替换法:
		str=str.replace(/正则表达式/后缀,function(a,b,c){
			console.log(a);//正则匹配到的关键字
			console.log(b);//正则匹配到的关键字的下标
			console.log(c);//原字符串
			return 判断a关键字的长度,并进行替换
		});

	3、格式化:身份证
		var id="500103198602215933";
		var reg=/(\d{6})(\d{4})(\d{2})(\d{2})(\d{4})/;
		id.replace(reg,function(a,b,c,d,e,f,g,h){
			//再replace的时候,正则出现了分组,形参数量增减,
                            //有几个分组就多几个形参
			//第1个分组获得的内容会保存在第2个形参之中
			//第2个分组获得的内容会保存在第3个形参之中
			//...
			//倒数第二个一定是下标
			//倒数第一个一定是原文本身
		})
	      格式化:手机号
		var phone="13452390312";
		var reg=/(\d{4})\d{4}(\d{3})/;
		
		phone=phone.replace(reg,(a,b,c)=>{
			return b+"****"+c;
		})
		
		console.log(phone);
                    
                    *****想要留下原字符串的哪部分,就把哪部分设置分组

	总结:何时前加^后加$,何时又该添加后缀g?
		1、前加^后加$ - 验证
		2、希望替换所有 - 必须加g

3.正则对象

1.创建:

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

2.API:

	1、验证:var bool=reg.test(用户输入的);