第三周笔记

192 阅读12分钟

第一天

BOM的常用对象

一、history对象:

    保存了当前窗口的历史纪录(过去的url)
    前进:history.go(1);
    后退:history.go(-1);
    刷新:history.go(0);

二、***location对象:

    保存了当前窗口的正在打开的url(现在的url)
    ***程序员常识:一个url由几部分组成?分别每个部分有什么用? - 以后再学习服务器端和数据库的时候会有很大的帮助
        5部分:
        1、协议:*https(加密)/*http(未加密)/ftp(传输文件)/ws(直播)...    前两个都属于叫做请求-响应模型
        2、主机号|IP地址|域名:域名是需要花钱购买的,主机号|IP地址是免费,127.0.0.1才真的是叫做主机号,只能自己访问自己
        3、端口号:https默认端口为443,http默认端口为80,只有默认端口可以省略不写
        4、***文件的相对路径|路由:百度加密了
        5、***查询字符串|请求消息:前端传输到后端的东西,前端对后端说的话,就是form表单提交带来的东西

        http://127.0.0.1:8020/js_core_day06/01history%E5%AF%B9%E8%B1%A1-3.html
        https://www.baidu.com/s?wd=%E5%80%9A%E5%A4%A9%E5%B1%A0%E9%BE%99%E8%AE%B0&rsv_spt=1&rsv_iqid=0x960794a60003bf35&issp=1&f=8&rsv_bp=1&rsv_idx=2&ie=utf-8&tn=44004473_20_oem_dg&rsv_enter=1&rsv_dl=tb&rsv_sug3=15&rsv_sug1=8&rsv_sug7=100&rsv_sug2=0&rsv_btype=i&inputT=4197&rsv_sug4=4198
属性:
        获取url的5个部分的内容,但是不需要记忆,你直接输入location对象即可查看
                协议:location.protocal;
                域名:location.hostname;
                端口:location.port;
                路由:location.pathname;
                请求消息:location.search;	

跳转:location="新url" - 替换当前窗口,可以后退
跳转后,禁止后退:location.replace("新url") - 替换当前窗口,禁止后退
刷新:location.reload();

DOM

    原本DOM是可以操作一切结构化文档的,但是再某一个升级后,为了方便各类程序员将DOM分为了3方面:
    1、核心DOM:无敌的,即可以操作HTML又可以操作XML,但是语法相对比较繁琐
    2HTML DOM:只可以操作HTML,不能访问一切自定义的东西,但是语法简单
    3、XML DOM:只可以操作XML,被淘汰了,被JSON数据格式代替了

一、查找元素

    1、通过关系找元素 
    2、直接找元素:
        1document.getElementsByXXXX(); - 返回的是一个动态集合HTMLCollection
        2、***2个:
            1var elem=document.querySelector("任意css选择器的"); //query-查询  selector-选择器:查询css选择器 
                    缺陷:只能找到单个元素,如果匹配到了多个,也只会返回第一个,没找到null
                            一次只能操作一个元素,不舒服

            2、***var elems=document.querySelectorAll("任意css选择器的");
                    优点:
                            1、找到了是一个集合,没找到是一个空集合
                            2、复杂查找时,非常简单
                            3、返回的是一个静态集合NodeList

面试题:document.getXXX 和 document.queryXXX的区别?

    1、后者更适合复杂查找
    2、动态集合和静态集合的区别?
            1、动态集合:每一次DOM发生变化,他都会悄悄的再次查找,让页面和数据保持一致,但是效率也就低下了 - 不支持forEach
            2、静态集合:每一次DOM发生变化,他不会悄悄的再次查找,让页面和数据没有保持一致,但是效率也就高了 - 支持使用forEach

二、操作样式

    1、内联样式

    2、样式表样式:- 此生不见
            //获取你想要操作的样式表
            var sheet=document.styleSheets[i];
            //获取此样式表种所有的样式规则
            var rules=sheet.cssRules;
            //数出你想要操作的那个规则的
            var rule=rules[i];
            //操作
            console.log(rule.style.css属性名)
            rule.style.css属性名="css属性值";

三、操作属性:

    1、*获取属性值:
            核心DOMelem.getAttribute("属性名");
            HTML DOMelem.属性名;

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

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

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

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

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

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

    1、创建空标签:
            var elem=document.createElement("标签名");

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

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

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

扩展:let创建变量

    1、创建变量:新增的一个let关键字:
	let 变量名=值;
	作用:
		1、解决了声明提前
		2、带来了块级作用域,一个{}就是一个块,此变量只能在那个{}里面使用
		3、如果用let去当作下标绑定事件,那么他会记录着你当前元素的下标,不再需要自定义下标了 - 其实forEach的那个形参i就是let创建的
    2、类数组转为普通数组:接住=Array.from(类数组对象);

第二天

一、递归(何时用、如何使用、算法、缺陷)

    何时:专门用于【遍历层级不明确的情况】 - DOM树和数据(children只能找到儿子层,找不到孙子层)
    如何使用:2步
    function 函数名(root){
            1、第一层要做什么直接做

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

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

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

二、绑定事件:三种方式:

    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、支持绑定多个函数对象
            缺点:有兼容性问题

扩展:select&option

    1select&option只有他们可以简化创建元素&上树:
       select.add(new Option("innerHTML","value"));

第三天

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

一、事件周期:

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

二、*****获取事件对象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、如果你使用elem.onclick=()=>{},那么elem.onclick=null

    2、如果你使用elem.addEventListener("事件名",回调函数); 那么:
            elem.removeEventListener("事件名",回调函数); - 事件名和回调函数,必须和添加时的一模一样

二、*****this的指向:非常多

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

三、*****ES5强制改变this的指向

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

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

    以后不是自己的方法,可以用,个人推荐:借,白嫖!
            三个固定套路:
                    1Math.max/min.apply(Math,arr) - 也能支持数组参数:
                    2Object.prototype.toString.call/apply(x)==="[object Array]";//鄙视题:判断xx是不也是一个数组
                    3、类数组转为普通数组:
                            1、接住=Array.prototype.slice.call/apply(类数组对象)
                            2、接住=Array.from(类数组对象)

四、ES6:

    1、学过了:letconst关键字、箭头函数

    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的解构赋值})
    4SetMap新的数据类型:
                1、*Set:类似于数组的一种数据格式 - 【去重数组,然后再转回数组】
                        var s=new Set(arr);
                        ...s - 三个点扩展运算符,可以脱掉数组的外套
                        一句话完成:[...new Set(arr)] - 不用记忆任何API

                2Map:类似于对象的一种数据格式
                        var m=new Map();
                        添加:m.set("键","值");
                        获取:m.get("键");
                        清空:m.clear();
                        删除:m.delete("键");
    5、新的循环:垃圾
	for(var v of arr){
		v;
	}

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

第五天

一、*****正则表达式:定义字符串中字符出现规则的表达式(何时用,如何用)

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

2.如何使用:语法:/正则表达式/(关键字原文、备选字符集、预定义字符集、量词、选择和分组、指定匹配位置、密码强度验证)

    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

三、正则对象

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

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