第三周

77 阅读8分钟

BOM常用对象

histore对象:保存了当前窗口的历史记录
    1、history.go(n)//前进,n代表前进几步
    2、history.go(-n)//后退,n代表后退几步
    3、history.go0//刷新
location对象:保存了当前窗口正在打开的url
    常识:一个url由几部分组成?每个部分分别有什么用?
        1、协议:https(加密)http(未加密)ftp(传输文件)ws(直播)
        2、主机号|IP地址|域名:域名需要花钱买,主机号|IP是免费的
        3、端口号:https默认端口号为443,thhp默认端口号为80,只有默认端口可以省略不写
        4、文件的相对路径|路由:百度加密了
        5、查询字符串|请求消息:前端传输到后端的东西,前端对后端说的话,就是form表单提交的东西
 跳转:location="新url"-替换当前窗口,可以后退
 跳转后,禁止后退:location.replace("新url")-替换当前窗口,禁止后退
 刷新;location。reload()

DOM对象

原本DOM是可以操作结构文档的,但是在某一个升级后,为了方便程序员将DOM分为了三方面    
    1、核心DOM:无敌的,即可以操作HTML又可以操作XML,但是语法相对比较繁琐
    2HTML DOM:只可以操作HTML,不能访问一切自定义的东西,但是语法简单
    3XML DOM:只可以操作XML,被淘汰了,被JSON数据格式代替了
查找元素
    var xxx=docution.querySelectorAll("任意css选择器")
        优点:
            1、找到了是一个集合,没找到是一个空集合
            2、复杂查找时,非常简单
            3、返回的是一个静态集合NodeList
     面试题:document.getXXXdocument.queryXXX的区别?
		1、后者更适合复杂查找
		2、动态集合和静态集合的区别?
		1、动态集合:每一次DOM发生变化,他都会悄悄的再次查找,让页面和数据保持一致,但是效率也就低下了 - 不支持forEach
		2、静态集合:每一次DOM发生变化,他不会悄悄的再次查找,让页面和数据没有保持一致,但是效率也就高了 - 支持使用forEach
 
操作属性:
	1、*获取属性值:
		核心DOM:elem.getAttribute("属性名");
		HTML DOM:elem.属性名;

	2、*设置属性值:
		核心DOM:elem.setAttribute("属性名","属性值");
		HTML DOM:elem.属性名="属性值";

	3、删除属性:设置属性值为空字符串,确实某些属性可以算是删除,但是只是删除了属性值,属性名还在,而有的属性哪怕只有一个属性名,也会具有作用(比如:href、disabled、readonly)
		*核心DOM:elem.removeAttribute("属性名");
		HTML DOM:elem.属性名=""; - 属性节点删不干净

	4、判断有没有:垃圾,只能判断有没有,不能判断是什么,推荐用elem.getAttribute("属性名");去获取到值,自己再写比较运算
		核心DOM:elem.hasAttribute("属性名");
		HTML DOM:elem.属性名!="";

	以后建议:优先HTML DOMHTML DOM实现不了的再用核心DOM补充!
		缺陷:
			1class必须写为className
			2、自定义的东西都操作不了

操作内容 - 你是学习完整的:innerHTML/innerText/Value

如何创建元素以及上树:31、创建空标签:
		var elem=document.createElement("标签名");

	2、为其设置必要的属性和事件
		elem.属性名="属性值";
		elem.on事件名=function(){}

	3、上树:3种
		*父元素.appendChild(elem);//在父元素末尾处追加一个子元素elem
		父元素.insertBefore(elem,已有子元素);//在父元素追加一个子元素elem,但是放在已有子元素的前面
		父元素.replaceChild(elem,已有子元素);//在父元素追加一个子元素elem,但是会替换掉已有子元素

6、删除元素:elem.remove();

    扩展:
        1、创建变量:新增的一个let关键字:
                let 变量名=值;
 递归:简单来说就是再函数之中再一次调用了函数自己,迟早有一天会停下来;
      何时:专门用于【遍历层级不明确的情况】 - DOM树和数据(children只能找到儿子层,找不到孙子层)
      如何使用:2function 函数名(root){
	1、第一层要做什么直接做

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

  算法:深度优先!优先遍历当前节点的子节点,子节点遍历完毕才会跳到兄弟节点
  缺陷:不要过多使用,性能相对较差,同时开启大量的函数调用,浪费内存,我们只在一个情况:【层级不明确】

  递归 vs 纯循环
递归:优点:简单易用
           缺点:性能低
纯循环:优点:几乎不占用性能
              缺点:难的一批

绑定事件:3种方式:
1、在HTML上书写事件属性
	<elem on事件名="函数名(实参)"></elem>
	缺点:
		1、不符合内容与样式与行为的分离原则
		2、无法动态绑定,一次只能绑定一个元素
		3、不支持绑定多个函数对象

2、*在js中使用事件处理函数属性
	elem.on事件名=function(){操作}
	优点:
		1、符合内容与样式与行为的分离原则
		2、动态绑定,一次能绑定多个元素
	缺点:
		1、不支持绑定多个函数对象

3、*在js中使用事件API:如果不用考虑老IE,他也不错
	主流:elem.addEventListener("事件名",callback);
	老IE:elem.attachEvent("on事件名",callback);
	兼容:
		if(elem.addEventListener){
			elem.addEventListener("事件名",callback);
		}else{
			elem.attachEvent("on事件名",callback);
		}
	优点:
		1、符合内容与样式与行为的分离原则
		2、动态绑定
		3、支持绑定多个函数对象
        缺点:有兼容性问题

属于BOM:重点只有两个:定时器 + event(事件对象);

1、事件周期:从事件发生,到所有事件处理函数执行完毕的全过程
        3个阶段:
	1、捕获阶段:由外向内,记录要发生的事件有哪些
	2、目标优先触发:目标元素->当前点击的实际发生事件的元素
	3、冒泡触发:由内向外,依次执行我们之前记录着的要发生的事件

2、*****获取事件对象event:
主流:会自动作为事件处理函数的第一个形参传入
老IE:event; - 老IE全局有这个变量
兼容:event;//第一次见到小三上位,不光老IE可用,主流也可用

得到了事件对象event可以做什么呢?
	1、获取鼠标的坐标:
		获取鼠标相对于屏幕的坐标:e.screenX/Y
		获取鼠标相对于窗口/客户端/文档显示区域的坐标:e.clientX/Y
		*获取鼠标相对于网页的坐标:e.pageX/Y

	2、阻止事件冒泡:- 鄙视面试中
		主流:e.stopPropagation();
		老IE:e.cancelBubble=true;
		兼容:e.cancelBubble=true;//第2次见到小三上位,不光老IE可用,主流也可用

	3、*****利用冒泡/事件委托 - 开发中常用,提升网页性能,有了它我们的事件函数也可以换为箭头函数了
		优化:如果多个子元素定义了相同 或 相似的事件操作,最好只给父元素定义一次
		为什么:每一次绑定一个事件函数,其实都是创建了一个事件对象,创建的事件对象越多,网站性能就越差
		淘汰了this,他水性杨花,当前元素
		认识一个目标元素target:你点击的是哪一个,他永远就是那一个,不会变化的
		主流:e.target;
		老IE:e.srcElement;
		兼容:e.srcElement;//第3次见到小三上位,不光老IE可用,主流也可用

	4、阻止浏览器的默认行为:比如:a标签默认就可以跳转,提交按钮可以提交表单,右键自带一个弹出框,F12自带一个控制台,F11自带全屏功能,F5自带刷新功能
		主流:e.preventDefault();
		老IE:e.returnValue=false;
		兼容:e.returnValue=false;//第4次见到小三上位,不光老IE可用,主流也可用

		新事件:
			1、右键事件 - window.oncontextmenu
			2、键盘事件:一般来说用于游戏开发较多+都要搭配上键盘的键码
				window.onkeydown - 按住和按下,任何键盘按键都可以触发
				window.onkeypress - 按住和按下,只有字母、数字、回车、空格可以触发,其他按键不行
				window.onkeyup - 松开,任何键盘按键都可以触发(比手速的游戏)

	5、获取键盘的键码:
                        e.keyCode; - 可以获取到你按了那个键,每个键都有自己对应的键码,但是不需要记忆,要么输出看,要么百度搜个表

                        event可以说是BOM之中最最重要的一个点,其他点就算你不用,你也要知道,笔试面试只要考BOM多半都是event

                        老IE:不支持HTML5和CSS3和ES5+      

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

何时使用:切割 替换 【验证】!
如何使用:语法:/正则表达式/
	1、最简单的正则就是关键字原文 "no" -> /no/后缀
		后缀:g:找全部		i:忽略大小写

	2、备选字符集:/^[备选字符集]$/
		强调:1、一个中括号,只管一位字符
		          2、问题:正则表达式默认只要满足就不管后续了,而我们做验证的人,希望的是用户从头到尾按照我们的要求来,希望从头到尾完全匹配:
			解决:前加^,后加$,两者同时使用,代表要求从头到尾完全匹配/^[备选字符集]$/ - 只要做验证必加!
		特殊:如果备选字符集中的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、密码强度验证:2-4位,可以输入数字、字母,但是必须出现一位大写和一位数字的组合
		/^[0-9A-Za-z]{2,4}$/
		预判公式:
			(?![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}/;//至少要有下划线
		

支持正则表达式的字符串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的时候,正则出现了分组,我们会得到更多的形参
			//再形参a的后面就会出现n个形参,就看你有多少个分组
			//第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、直接量:var reg=/正则表达式/后缀;
	2、构造函数:var reg=new RegExp("正则表达式","后缀");

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