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,但是语法相对比较复杂
2、HTML 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选择器去查找元素
1、var 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、买是不会立刻调用的,需要自己手动调用一下
三个固定套路:
1、Math.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、解构赋值
顾名思义:解析结构再进行复制 - 赋值的新方式,并且得到了增强!
如果赋值符号,左右两边的结构是一样的,他就会悄悄的解开/脱掉结构再一一进行赋值
7、Set和Map:两个新的数据类型
1、Set:有一点点用,类似于数组的一种数据格式,但是远不如数组牛逼(没几个API,能做的事少) - 【去重数组,然后再转回数组】
[...new Set(arr)];
... - 扩展运算符,可以脱掉数组/对象的衣服不需要记忆set任何的API,完全比不上数组的API
2、Map:垃圾:类似于对象的一种数据格式,完全不如对象\
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->验证失败