JS第三周总结

135 阅读11分钟

BOM常用对象三个点:定时器、客户端存储技术、event

1、history对象:保存了当前窗口的历史记录(过去的url)

前进:history.go(正数)
后退:history.go(负数);
刷新:history.go(0);

** 2、location对象:保存了当前窗口的正在打开的url(现在的url)**

程序员必备常识:一个url由几部分组成?分别每个部分是什么?有什么作用?

5部分:

1、协议:http(未加密)/https(加密)/ftp(传输文件的)/ws(直播)... - 前两个都属于叫做 请求 - 响应 模型,专门用于实现网站开发
2、主机号|域名|IP地址:域名是需要花钱购买的,主机号|IP地址是免费的,127.0.0.1才叫主机号,只能自己访问自己
3、端口号:https默认端口为443,http默认端口为80,只有默认端口可以省略不写
4、文件的相对路径|路由:百度加密了 - 如果以后学习了服务器端,我们可以配置好一些选项,用户就可以再自己的电脑上看到我们的东西了
5、查询字符串|请求消息:前端传输到后端的东西,前端对后端说的话(请求),就是form表单get提交带来的东西

协议://域名:端口号/路由?请求消息

属性:获取url的5个部分的内容,但是不需要记忆,直接输出location对象即可查看

协议:location.protocol
域名:location.hostname
端口号:location.port;
路由:location.pathname;
请求消息:location.search;

方法:

跳转:location="新url";
跳转后,禁止后退:location.replace("新url");
刷新:location.reload();

3、DOM:原本DOM是可以操作一切结构化文档的,但是再某个版本升级过后,为了方便各类程序员将DOM分为了3分布

1、核心DOM:无敌的,既可以操作HTML又可以操作XML,但是语法相对比较复杂
2HTML DOM:只能操作HTML,不能访问一些自定义的东西,但是语法比较简单	
3、XML DOM:只能操作XML,被淘汰了,被JSON数据格式代替了
建议:优先使用HTML DOM,因为他更简单,HTML DOM实现了不得,再用核心DOM补充

查找元素:2方面

1、关系:前提:至少要找到一个元素,才可以调用关系网

子:elem.children; - 集合
第一个儿子:elem.firstElementChild;
最后一个儿子:elem.lastElementChild;
前一个兄弟:elem.previousElementSibling;
后一个兄弟:elem.nextElementSibling;

2、直接找元素:2大类:通过HTML的特性去查找元素

1、var elems=document.getElementsByXXXXX();//返回的是一个动态集合HTMLCollection

2、第二大类:2个:通过CSS选择器去查找元素

1var elem=document.querySelector("任意css选择器");
缺点:只能找到单个元素,如果匹配到多个,也只会返回第一个,没找到,返回null	
     一次只能操作一个元素
2、***var elems=document.querySelectorAll("任意css选择器");
优点:
	1、找到了是一个集合,没找到是一个空集合
	2、复杂查找时,非常的舒服
	3、返回的是一个静态集合NodeList

2、操作样式:

1、内联样式:

获取:elem.style.css属性名; - 只能获取内联样式
设置:elem.style.css属性名="css属性值";

2、样式表样式 不怎么用

3、操作属性:

1、获取属性值:

核心DOM:elem.getAttribute("属性名");
HTML DOM:elem.属性名;

2、设置属性值:

核心DOM:elem.setAttribute("属性名","属性值");
HTML DOM:elem.属性名="属性值";

3、删除属性:

设置属性值为空字符串,确实某些属性可以算是删除了,但是只是删除了属性值,属性名还在,而有的属性哪怕只有一个属性名,也会具有作用!(checked、readonly、href)

核心DOM:elem.removeAttribute("属性名");
HTML DOM:elem.属性名="";

5、如何创建元素以及上树:3步

1、创建空标签:

var elem=document.createElement("标签名");

2、为其设置必要的属性和事件

elem.属性名="属性值";
elem.on事件名=function(){}

3、上树:3种

1、父元素.appendChild(elem);//在父元素末尾追加一个子元素elem
2、父元素.insertBefore(elem,已有子元素);//在父元素里面追加一个子元素elem,但是会放到你的已有子元素的前面
3、父元素.replaceChild(elem,已有子元素);//在父元素里面追加一个子元素elem,但是会替换掉你的已有子元素

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

input/textarea的两个专属事件

onfocus(获取焦点)和 onblur(失去焦点)

2、创建变量的新方式:

ES6带来了一个关键词let - 建议忘掉var

let 变量名=值; 作用:

1、解决了声明提前,一定先创建,后使用
2、带来了块级作用域,一个{}就是一个块
3、如果你用let当作下标去绑定事件,那么他会记录着你当前元素的下标,不需要再自定义下标了!其实forEach的那个形参i也是用let创建的!
    

3、类数组对象变为普通数组!ES5提供了此方法

接住=Array.from(类数组);

事件周期:从事件发生,到所有事件处理函数执行完毕的全过程:

3个阶段:

1、捕获阶段:由外向内,记录着要发生的事件有哪些
2、目标优先触发:目标元素->当前点击的实际发生事件的元素
3、冒泡触发:由内向外,依次执行我们之前记录着的要发生的事件

获取事件对象event:

主流:会自动作为事件处理函数的第一个形参传入e
老IE:event;
兼容:event;

得到了事件对象event可以做什么

1、获取鼠标的坐标/位置:3种

获取鼠标相对于屏幕的坐标:e.screenX/Y;
获取鼠标相对于浏览器窗口/客户端/文档显示区域的坐标:e.clientX/Y
获取鼠标相对于网页的坐标:e.pageX/Y;

2、阻止冒泡

主流:e.stopPropagation();
老IE:e.cancelBubble=true; 
兼容:e.cancelBubble=true;

3、事件委托/利用冒泡:开发中常用,提升网页性能

优化:如果多个子元素定义了 相同 或 相似的事件操作,那么最好只给【父元素】绑定一次。

为什么:每一次绑定一个事件函数,其实都是创建了一个事件对象,创建的对象越多,网页的性能越差。

淘汰了this,认识一个新的人叫做【目标元素】:实际触发事件的元素

主流:e.target;
老IE:e.srcElement;
兼容:e.srcElement;

4、阻止浏览器的默认行为

主流:e.preventDefault();
老IE:e.returnValue=false;
兼容:e.returnValue=false;

1、右键事件 - window.oncontextmenu

2、键盘事件:

window.onkeydown - 按下和按住都会触发,而且任何按键都会触发!
window.onkeypress - 按下和按住都会触发,但是只有数字、字母、回车、空格可以触发,其他不行!
window.onkeyup - 松开的时候才会触发,而且任何按键都会触发!比手速的游戏才会用他。

5.获取键盘的键码

e.keyCode-可以获取到按了哪个键了,每个键都有自己对应的键码,百度看e.keyCode表

递归:

简单来说就是在函数中再一次调用了函数自己,但是迟早有一天我们要让他停下来。

何时使用:

专门用于【遍历层级不明确】的情况 - DOM树和【数据】

如何使用

function 函数名(root){
1、root第一层要做什么直接做
2、判断有没有下一层,如果有下一层再次调用此方法,但是传入的实参是自己的下一层
	}
	函数名(实际的根元素)

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

递归 vs 纯循环

递归:优点:简单易用
	缺点:性能低
纯循环:优点:性能高
	缺点:难得很

绑定事件:3种方式

1、在HTML页面上书写事件属性

	<elem on事件名="函数名()"></elem>
	缺点:
1、不符合内容(HTML)与样式(CSS)与行为(JS)的分离
2、无法动态绑定,一次只能绑定一个元素
3、不支持绑定多个函数对象

2、在JS中使用事件处理函数属性

elem.on事件名=function(){操作}
优点:
	1、符合内容(HTML)与样式(CSS)与行为(JS)的分离
	2、动态绑定,一次可以绑定多个元素
	3、不存在兼容性问题
缺点:
	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、符合内容(HTML)与样式(CSS)与行为(JS)的分离
		2、动态绑定,一次可以绑定多个元素
		3、支持绑定多个函数对象
	缺点:
		具有兼容性问题:老IE不能使用

	
**现在的趋势不是PC端而是移动端,不存在IE浏览器**

select&option 只有他们可以简化创建和上树

select.add(new Option("innerHTML","value")

事件的取消绑定:

1.事件的取消绑定:

1、如果你用的elem.on事件名=()=>{},那么你想要取消绑定:elem.on事件名=null
2、如果你用的elem.addEventListener("事件名",f1),那么你想要取消绑定:elem.removeEventListener("事件名",f1),事件名和回调函数,【必须和添加时一模一样,是同一个】

2、this的指向:

1、单个元素绑定事件,this->这个元素
2、多个元素绑定事件,this->当前触发事件的元素
3、箭头函数中的this->外部对象
4、函数中的this->当前正在调用函数的这个人
5、定时器的this->window

3、ES5强制改变this的指向:

call/apply:临时的替换了函数之中的this - 借用

语法:

1、函数名.call(借用的对象,实参,...) - 单独传入每个实参 
2、函数名.apply(借用的对象,arr) - 只能传入一个实参,要求必须是一个数组:apply其实悄悄会将数组打散
强调:call/apply,相当于立刻调用函数,是会立刻执行的,而且会还给别人,才叫借用

bind:永久的替换了函数中的this - 买

语法:

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

三个固定套路:

1Math.max/min.apply(Math,arr);
2、类数组转为普通数组:
老方法:接住=Array.prototype.slice.call/apply(类数组)
新方法:接住=Array.from(类数组)

ES6:大版本

1、let 变量名=值;

2、const 常量名=值;

3、箭头函数:简化一切的回调函数(没有函数名、也没有自调过),function去掉,()和{}之间添加=>,形参一个,省略小括号,函数体一句话,省略大括号,如果函数体一句话并且是return,return和{}都省略

4、模板字符串:可以直接识别变量,不需要用+运算再去拼接了,而且实现了一个简单的JS的环境,甚至支持在里面使用API做操作我的名字叫 ${name}

5、解构赋值

顾名思义:解析结构再进行复制 - 赋值的新方式,并且得到了增强!

如果赋值符号,左右两边的结构是一样的,他就会悄悄的解开/脱掉结构再一一进行赋值

7067e070def85fc4acf8a6ea475c96c.png 7、Set和Map:两个新的数据类型

1Set:有一点点用,类似于数组的一种数据格式,但是远不如数组牛逼(没几个API,能做的事少) - 【去重数组,然后再转回数组】
               [...new Set(arr)];
               ... - 扩展运算符,可以脱掉数组/对象的衣服不需要记忆set任何的API,完全比不上数组的API
2Map:垃圾:类似于对象的一种数据格式,完全不如对象\

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

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

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

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

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

2、备选字符集:/[备选字符集]/;

强调:

1、一个中括号,只管一位字符
2、问题:正则表达式默认只要满足了就不管后续了,而我们做验证的人,希望的是用户从头到尾完全按照我们的要求来,希望完全匹配
解决:前加^后加$,两者同时使用,代表要求从头到尾【完全匹配】 - /^[备选字符集]$/;
  • 一位数字:[0-9]
  • 一位字母:[a-zA-Z]
  • 一位数字、字母、下划线:[0-9A-Za-z_]
  • 一位汉字:[\u4e00-\u9fa5]
  • 一位数字、字母、下划线、波浪号、汉字:[0-9A-Za-z_~\u4e00-\u9fa5

3、预定义字符集:

  • 一位数字:\d
  • 一位数字、字母、下划线:\w
  • 一位空白字符:\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]+$) -> 不能全由数字组成,可能有大写、小写、汉字、日文、韩文、特殊符号...
(?![0-9a-z]+$) -> 不能全由数字组成,也不能全由小写组成,也不能全由数字和小写的组合组成,可能有大写、汉字、日文、韩文、特殊符号...
(?![0-9A-Za-z]+$) -> 不能全由数字组成,也不能全由小写组成,也不能全由数字和小写的组合组成,也不能全由数字和大写的组合组成,也不能全由大字和小写的组合组成,也不能全由数字和大写和小写的组合组成,
//2-4,可以输入数字、字母、但是必须出现一位大写和一位数字的组合?
			var reg=/^(?![0-9a-z]+$)(?![A-Za-z]+$)[0-9A-Za-z]{2,4}$/;
//2-4,可以输入数字、字母、但是必须出现3者的组合?
			var reg=/^(?![0-9a-z]+$)(?![A-Za-z]+$)(?![A-Z0-9]+$)[0-9A-Za-z]{2,4}$/;

2.支持正则的字符串API:

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

2、替换:

1、基础替换法:

var newStr=str.replace(RegExp,"新内容");

2、高级替换法:

var newStr=str.replace(/[卧我握窝][槽肏操草曹糙去]+/g,function(key,i,str){
		console.log(key);//关键字
		console.log(i);//关键字的下标
		console.log(str);//原文本身
		return a.length==2?"**":"***";});

3、格式化:

  var idCard="500103198602215933";
  var reg=/(\d{6})(\d{4})(\d{2})(\d{2})(\d{4})/;
  var newStr=idCard.replace(reg,function(a,b,c,d,e,f,g,h){
 //在replace的时候,如果正则中出现了分组,那我们会得到更多的形参
//在形参key的后面就会出现n形参,具体有多少个,看你有多少个分组
//第1个分组获得的内容回保存到第2个形参之中
//第2个分组获得的内容回保存到第3个形参之中
//第3个分组获得的内容回保存到第4个形参之中
//...
//倒数第二个是下标
//倒数第一个是原文
return `${c}${d}${e}日`;
		})

3、正则对象:

创建:

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

API:

验证:var bool=reg.test(str);
true->验证成功	false->验证失败