js第三周学习笔记

147 阅读11分钟

day1 BOM常用对象以及DOM元素选择

1、BOM常用对象:

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

前进:history.go(1);
后退:history.go(-1);
刷新:history.go(0);

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

1、程序员常识:url的组成:

 url由5部分组成:
  1、协议:https(加密)/http(未加密)/ftp(传输文件)/ws(直播)
   https和http叫做请求——响应模式
  2、主机号/ip地址/域名:域名是需要购买的,主机号/ip地址是免费的,127.0.0.1才是真正的主机号,只能自己访问自己
  3、端口号:https默认的端口号为443,http默认的端口号为80,只有默认的端口号才可以省略
  4、文件的相对路径/路由
  5、查询字符串/请求消息:前端传到后端的东西,前端对后端说的话

2、location属性:获取url的5个部分的内容

 1、协议:location.protocol
 2、域名:location.hostname
 3、端口:location.port
 4、路由:location.pathname
 5、请求消息:location.search
 跳转:location="新url"——替换当前窗口,可以后退
 跳转并禁止后退:location.replace("新url")——替换当前窗口禁止后退

2、DOM

1、查找元素:

1、通过关系查找

2、直接找元素:

 1、document.getElementsByXXX();——返回动态集合
 2、document.querySelectorAll("任意css选择器");——返回静态集合没找到是空集合
面试题:document.getElementsByXXX()和document.querySelectorAll("任意css选择器")的区别
 1、后者更适合复杂查找
 2、动态集合和静态集合的区别:
   1、动态集合:每一次DOM发生变化,它都会悄悄再次查找,让页面和数据渲染保持一致,同时效率也更加低下了,它也不支持用forEach去遍历
   2、静态集合:每一次DOM发生变化,它不会悄悄再次查找,让页面和数据渲染保持一致,效率提高了,它支持forEach遍历

2、操作属性:

1、获取属性值:

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

2、设置属性值:

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

3、删除属性:设置属性值为空有些时候确实能达到属性消除的效果,但是有些就不行,所以不建议这么做

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

4、判断有没有:垃圾还不如自己获取属性值值自己写判断

核心DOM:elem.hasAttribute("属性名");
HTMLDOM:elem.属性名!="";

建议:以后先用HTML DOM,HTML DOM 实现不了的再考虑使用核心DOM
缺陷:
 1、class必须写为className
 2、自定义的东西操作不了,必须使用核心DOM

3、如何创建元素及上树

1、创建空标签:

let elem=document.creatElement("标签名");

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

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

3、上树:3种

父元素.appendChild(elem);//父元素内末尾处追加一个子元素
父元素.insertBefore(elem,已有子元素)//在父元素内追加一个子元素,但是放在已有的子元素之前
父元素.replaceChild(elem,已有子元素)//在已有的子元素的位置替换为elem

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

扩展:  1、创建变量:新增一个let关键字

let 变量名=值;

  作用:
   1、解决了声明提前
   2、带来了块级作用域,一个{}就是一个块级作用域,此变量只能在当前块级中使用
   3、如果用let去当做下标去绑定事件,那么它会记录下你当前元素的下标,就不需要去定义下标了——forEach中的i就是用let创建的
 2、类数组对象转为普通数组:接住=Array.from(类数组对象);

day2递归和事件绑定

1、递归:简单来说就是函数之中再一次调用函数自己,迟早有一天会停下来

1、何时使用:专门用于遍历层级不明确的情况——DOM树和数据

2、如何使用:2步

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

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

2、绑定事件:3种

1、在HTML中书写事件属性

<elem on事件名="函数名(实参)"></elem>

 缺点:
  1、不符合内容与样式与行为分离的规则
  2、无法动态绑定,一次只能绑定一个元素
  3、不支持绑定多个函数对象

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

elem.on事件名=function(){}

 优点:
  1、符合规则
  2、动态绑定,一次能绑定多个元素
 缺点:
  1、不支持绑定多个函数对象:

3、在js中使用事件API:如果不考虑老IE此方法也不错

主流:

elem.addEventListener("on事件名",callback);

老IE:

elem.attchEvent("on事件名",callback);

兼容:

if(elem.addEventListener){
    elem.addEventListener("on事件名",callback);
}else{
    elem.attchEvent("on事件名",callback);
}

day3Event事件和周期函数:

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

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

2、获取事件对象Event:

 主流:会自动为事件处理函数
 老IE:event;老IE全局有这个变量
 兼容:event:
 得到事件对象可以做些什么:
  1、捕获鼠标的坐标:
   1、相对于屏幕的坐标:e.screenX/Y;
   2、相对于窗口/客户端/文档显示区域的坐标:e.clientX/Y;
   3、相对于网页的坐标:e.pageX/Y;
  2、阻止事件冒泡:笔试题:
   主流:e.stopPropagation();
   老IE:e.cancelBubble=true;
   兼容:e.cancelBubble=true;

3、利用冒泡/事件委托

 开发中经常使用,提升网页性能,有了它我们的事件函数也就可以转换为箭头函数了
  优化:如果多个子元素定义了相同或者相似的操作事件操作,最好只给父元素定义一次
  为什么要用事件委托:每一次绑定一个事件函数,其实都是建立了一个事件对象,创建的事件对象越多,网站的性能越差
  用了此方法以后淘汰了this,换了一个新的目标元素e.target,用户点击哪一个,target就指向哪一个
  语法:

主流: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;可以知道你按了哪个键,每个键都有自己的键码,你不用记忆。

总结:event是BOM中最重要的知识点,其他的就算不用但也要知道,面试和笔试中BOM最常考的就是event!!!

day4、事件取消和更改this指向

1、事件的取消绑定:

 1、如果你使用的是elem.inclick=()=>{};那么elem.onclick=null;
 2、如果使用的是elem.addEventListener("事件名",callback);
  那么取消就是:elem.removeEventListener("事件名",callback);事件名和回调函数名必须一模一样

2、this的指向:非常多

 单个元素绑定事件,this指向就是这一个元素

 多个元素绑定,this的指向当前触发事件的元素
 箭头函数中this的指向是外部对象
方法中的this的指向是调用此方法的元素
 定时器的this指向的是window

3、强制更改this的指向

1、call/apply:临时替换了函数的this——借用

语法:

需要借用的函数名.call(借用多的对象,实参1,实参2....);
需要借用的函数名.apply(借用多的对象,[实参数组]);

强调:call、apple都是相当于立刻调用了函数,立即执行的

2、bind:永久替换了函数中的this

 3件事:
  1、创建了一个和原函数完全相同的函数
  2、将新的函数中的this永久绑定为指定对象,别人无法借用
  3、将新函数的部分参数永久固定
语法:

var 新函数名=原函数名.bind(永久对象,永久实参);

强调
 1、此方法不是立即执行的,需要后期调用执行
 2、bind绑定的新函数不能再被call/qpply借用
以下改变this指向的三个固定套路:
 1、Math.max/min.apply(Math,arr);
 2、笔试题:判断XX是不是一个数组对象:
Object.prototype.toString.call/apply(XX)=="[object Array]";
 3、类数组转为普通数组:
  1、接住=Array.prototype.slice.call/apply(类数组对象);
  2、接住:Array.from(类数组对象);

4、ES6的新内容:

1、模板字符串:``:

  可以直接识别变量,不需要再使用+运算去拼接了。而且可以是实现一个简单的js环境,甚至可以直接在里面书写API
实例:`我的名字叫${name}`

3、**解构赋值**

 含义:解析结构再进行赋值操作,如果赋值符号两边的内容结构是一样的,就会悄悄地进行解开/脱掉结构再进行一一赋值
 语法:
  1、类似数组的解构赋值:

let [a,b,c]=[1,2,3];

  2、类似对象的解构赋值:

let {a,b=默认值,c}={c:3,a:!,b:2};//形参可以设置默认值,如果自己传入了,就用自己的

 作用:
  1、调用函数时,传入的实参的顺序无所谓了

function zwjs({name,age,hobby="女"}){
    return `我的名字叫${name},今年${age}岁,爱好${hobby}`;
}
console.log(zwjs({hobby:"学习",age:18,name:"大大"}));

  2、函数的返回结果有很多个

function f1(){
    let a=1;
    let b=2;
    return [a,b];
}
let [a,b]=f1();
console.log(a,b);

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

5、新的数据类型Set

1、Set:类似于数组的新的纾解类型

 作用:数组去重

let s=new Set(arr);
去重arr的操作:
[...new Set(arr)]

day5**正则表达式和验证**

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

 何时使用:切割、替换、验证
 如何使用:语法:/正则表达式/

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
  一位数字、字母、下划线:\w
  一位空白字符:\s
  一位除了换行以外的任意字符: .
优先使用预定义字符集,预定义字符集不满足时才考虑用备选字符集进行补充
不管是备选字符集还是预定义字符集,一个都只管一位

4、量词:规定一个字符集出现的次数

  1、有明确数量:
   字符集{n,m}:前边相邻的字符集,至少有n个,最多有m个
   字符集{n,}:前边相邻的字符集,至少有n个,最多有无限
   字符集{n}:前边相邻的字符集,只能有n个
  2、无明确数量:
   字符集?:前边相邻的字符集,可有可无,最多1个
   字符集*:前边相邻的字符集,可有可无,多了不限
   字符集+:前边相邻的字符集,至少1个,最多1个

5、选择和分组:通常在一起使用

  选择:|在两个规则中选一个
   /^规则1|规则2$/
  分组:()将多个字符集临时组成了一组新规则
   /^(规则1|规则2)$/

6、制定匹配位置:

  ^ 开头;
  $结尾;
  要求从头到尾完全匹配:前加^后加$

7、密码强度验证:2-4位,可以输入数字、字母、但是必须出现一位大写和小写的组合:

  正则表达式:/^[0-9a=zA=Z]{2,4}$/
  预判公式:(?![]+$)
   (?![0-9]+$)—>不能全是数字组成,可能含有其他字符
   (?![a-z]+$)—>不能全是小写字母,可能有其他字符
   (?![0-9a-z]+$)—>不能全是数字也不能全是字母也不能全由数字和小写字母组成

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

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

2、替换:很有可能出现在笔试题中

  1、基本替换法:replace支持正则,并且配上后缀g可以找到全部
  此方法的缺陷:替换的新内容是固定的

str=str.replace(/正则表达式/后缀,"新内容")

  2、高级替换法:

str=str.replace(/正则表达式/后缀,function(a,b,c){
    //a:正则匹配到的关键字
    //b:正则匹配到的关键字的下标
    //c:原字符串
    return 判断a关键字的长度而返回不同的数量
})

  3、格式化身份证:
   在replace的回调方法中,如果分组越多,会得到更多的形参:
   ; 第一个形参永远是正则匹配到的关键字
   ; 第n个分组保存在第n+1个形参之中
   ; 倒数第二个形参永远是是匹配到的关键字的下标
   ; 倒数第一个形参永远是原字符串

let id="身份证号";
let reg=/\d{6}(\d{4})(\d{2})(\d{2})\d{4}/
id.replace(reg,function(a,b,c,d,e,f){
    return 想要输出的内容
})

总结:何时前加^后加,何时又加上后缀g?<br> &emsp;1、前加^后加用作验证
 2、加后缀g:替换,替换所有想要替换的

3、正则对象:

 1、创建:
  1、直接量:let reg=/正则表达式/后缀
  2、构造函数:let reg=new RegExp("正则表达式","后缀");
 2、API:
  1、验证:let bool=reg.test(用户输入的内容);